From 476b89009e0ff07b81fcb866a646d556b1846e23 Mon Sep 17 00:00:00 2001 From: Starknet Dev Date: Sat, 14 Sep 2024 11:32:50 -0400 Subject: [PATCH 1/7] - add syscall for updating adventure name - add component in adventurer list card to change the name - add support in the indexer for tracking changed name events --- indexer/src/adventurers.ts | 80 ++++++++++------- indexer/src/utils/events.ts | 8 +- indexer/src/utils/helpers.ts | 18 +++- .../components/start/AdventurerListCard.tsx | 88 ++++++++++++++++--- .../app/components/start/AdventurersList.tsx | 43 +++++---- ui/src/app/containers/AdventurerScreen.tsx | 7 ++ ui/src/app/lib/utils/syscalls.ts | 49 +++++++++++ ui/src/app/page.tsx | 2 + 8 files changed, 232 insertions(+), 63 deletions(-) diff --git a/indexer/src/adventurers.ts b/indexer/src/adventurers.ts index 8fff81c7e..d2e67197d 100644 --- a/indexer/src/adventurers.ts +++ b/indexer/src/adventurers.ts @@ -1,57 +1,60 @@ import type { Config } from "https://esm.sh/@apibara/indexer"; -import type { Block, Starknet } from "https://esm.sh/@apibara/indexer/starknet"; -import type { Mongo } from "https://esm.sh/@apibara/indexer/sink/mongo"; import type { Console } from "https://esm.sh/@apibara/indexer/sink/console"; +import type { Mongo } from "https://esm.sh/@apibara/indexer/sink/mongo"; +import type { Block, Starknet } from "https://esm.sh/@apibara/indexer/starknet"; +import { MONGO_CONNECTION_STRING } from "./utils/constants.ts"; +import { getLevelFromXp } from "./utils/encode.ts"; import { + ADVENTURER_DIED, ADVENTURER_UPGRADED, + AMBUSHED_BY_BEAST, + ATTACKED_BEAST, + ATTACKED_BY_BEAST, + DISCOVERED_BEAST, DISCOVERED_GOLD, DISCOVERED_HEALTH, + DISCOVERED_LOOT, + DODGED_OBSTACLE, + DROPPED_ITEMS, + EQUIPPED_ITEMS, + FLEE_FAILED, + FLEE_SUCCEEDED, + HIT_BY_OBSTACLE, + ITEMS_LEVELED_UP, + parseAdventurerDied, parseAdventurerUpgraded, + parseAmbushedByBeast, + parseAttackedByBeast, + parseDiscoveredBeast, parseDiscoveredGold, parseDiscoveredHealth, - parseStartGame, - START_GAME, - PURCHASED_ITEMS, - ATTACKED_BY_BEAST, - ADVENTURER_DIED, - parseAdventurerDied, - parseAttackedByBeast, - AMBUSHED_BY_BEAST, - parseAmbushedByBeast, - ATTACKED_BEAST, - SLAYED_BEAST, - parseSlayedBeast, - FLEE_FAILED, + parseDiscoveredLoot, + parseDodgedObstacle, + parseDroppedItems, + parseEquippedItems, parseFleeFailed, - FLEE_SUCCEEDED, parseFleeSucceeded, - ITEMS_LEVELED_UP, + parseHitByObstacle, parseItemsLeveledUp, - EQUIPPED_ITEMS, parsePurchasedItems, - parseEquippedItems, - DROPPED_ITEMS, - parseDroppedItems, - HIT_BY_OBSTACLE, - parseHitByObstacle, - DODGED_OBSTACLE, - parseDodgedObstacle, - UPGRADES_AVAILABLE, + parseSlayedBeast, + parseStartGame, + parseTransfer, + parseUpdateAdventurerName, parseUpgradesAvailable, - DISCOVERED_BEAST, - parseDiscoveredBeast, - DISCOVERED_LOOT, - parseDiscoveredLoot, + PURCHASED_ITEMS, + SLAYED_BEAST, + START_GAME, TRANSFER, - parseTransfer, + UPDATE_ADVENTURER_NAME, + UPGRADES_AVAILABLE, } from "./utils/events.ts"; import { insertAdventurer, updateAdventurer, + updateAdventurerName, updateAdventurerOwner, } from "./utils/helpers.ts"; -import { MONGO_CONNECTION_STRING } from "./utils/constants.ts"; -import { getLevelFromXp } from "./utils/encode.ts"; const GAME = Deno.env.get("GAME"); const START = +(Deno.env.get("START") || 0); @@ -83,6 +86,7 @@ const filter = { { fromAddress: GAME, keys: [UPGRADES_AVAILABLE] }, { fromAddress: GAME, keys: [ADVENTURER_UPGRADED] }, { fromAddress: GAME, keys: [TRANSFER] }, + { fromAddress: GAME, keys: [UPDATE_ADVENTURER_NAME] }, ], }; @@ -352,6 +356,16 @@ export default function transform({ header, events }: Block) { ]; } } + case UPDATE_ADVENTURER_NAME: { + console.log("UPDATE_ADVENTURER_NAME", "->", "ADVENTURER UPDATES"); + const { value } = parseUpdateAdventurerName(event.data, 0); + return [ + updateAdventurerName({ + adventurerId: value.adventurerId, + adventurerName: value.name, + }), + ]; + } default: { console.warn("Unknown event", event.keys[0]); return []; diff --git a/indexer/src/utils/events.ts b/indexer/src/utils/events.ts index d93501c1f..0c0486cca 100644 --- a/indexer/src/utils/events.ts +++ b/indexer/src/utils/events.ts @@ -8,8 +8,8 @@ import { parseU128, parseU16, parseU256, - parseU64, parseU32, + parseU64, parseU8, } from "./parser.ts"; @@ -53,6 +53,7 @@ export const NEW_COLLECTION_TOTAL = eventKey("NewCollectionTotal"); // Tokens export const TRANSFER = eventKey("Transfer"); export const CLAIMED_FREE_GAME = eventKey("ClaimedFreeGame"); +export const UPDATE_ADVENTURER_NAME = eventKey("UpdateAdventurerName"); export const parseStats = combineParsers({ strength: { index: 0, parser: parseU8 }, @@ -384,3 +385,8 @@ export const parseNewCollectionTotal = combineParsers({ xp: { index: 1, parser: parseU32 }, gamesPlayed: { index: 2, parser: parseU32 }, }); + +export const parseUpdateAdventurerName = combineParsers({ + adventurerId: { index: 0, parser: parseFelt252 }, + name: { index: 1, parser: parseFelt252 }, +}); diff --git a/indexer/src/utils/helpers.ts b/indexer/src/utils/helpers.ts index 926a8e4bc..a267c0a4e 100644 --- a/indexer/src/utils/helpers.ts +++ b/indexer/src/utils/helpers.ts @@ -1,5 +1,5 @@ +import { checkExistsInt, computeHash, getLevelFromXp } from "./encode.ts"; import { parseAdventurerState } from "./events.ts"; -import { computeHash, checkExistsInt, getLevelFromXp } from "./encode.ts"; export function insertAdventurer({ id, @@ -235,6 +235,22 @@ export function updateAdventurerOwner({ }; } +export function updateAdventurerName({ adventurerId, adventurerName }: any) { + const entity = { + id: checkExistsInt(parseInt(adventurerId)), + }; + + return { + entity, + update: { + $set: { + ...entity, + name: checkExistsInt(BigInt(adventurerName).toString(16)), + }, + }, + }; +} + export function insertDiscovery({ txHash, adventurerId, diff --git a/ui/src/app/components/start/AdventurerListCard.tsx b/ui/src/app/components/start/AdventurerListCard.tsx index fa1f366f2..daf5eca62 100644 --- a/ui/src/app/components/start/AdventurerListCard.tsx +++ b/ui/src/app/components/start/AdventurerListCard.tsx @@ -1,17 +1,18 @@ -import { useEffect, useState } from "react"; +import Info from "@/app/components/adventurer/Info"; import { Button } from "@/app/components/buttons/Button"; +import useAdventurerStore from "@/app/hooks/useAdventurerStore"; +import useNetworkAccount from "@/app/hooks/useNetworkAccount"; +import useTransactionCartStore from "@/app/hooks/useTransactionCartStore"; +import { padAddress } from "@/app/lib/utils"; import { Adventurer } from "@/app/types"; -import Info from "@/app/components/adventurer/Info"; +import { useProvider } from "@starknet-react/core"; +import { ChangeEvent, useEffect, useState } from "react"; import { AccountInterface, + constants, Contract, validateAndParseAddress, - constants, } from "starknet"; -import useTransactionCartStore from "@/app/hooks/useTransactionCartStore"; -import { useAccount, useProvider } from "@starknet-react/core"; -import useAdventurerStore from "@/app/hooks/useAdventurerStore"; -import { padAddress } from "@/app/lib/utils"; import { StarknetIdNavigator } from "starknetid.js"; import { CartridgeIcon, StarknetIdIcon } from "../icons/Icons"; @@ -25,6 +26,11 @@ export interface AdventurerListCardProps { from: string, recipient: string ) => Promise; + changeAdventurerName: ( + account: AccountInterface, + adventurerId: number, + name: string + ) => Promise; } export const AdventurerListCard = ({ @@ -32,8 +38,9 @@ export const AdventurerListCard = ({ gameContract, handleSwitchAdventurer, transferAdventurer, + changeAdventurerName, }: AdventurerListCardProps) => { - const { account, address } = useAccount(); + const { account, address } = useNetworkAccount(); const { provider } = useProvider(); const starknetIdNavigator = new StarknetIdNavigator( provider, @@ -55,6 +62,10 @@ export const AdventurerListCard = ({ "send" | "addToCart" | null >(null); + const [isEditOpen, setIsEditOpen] = useState(false); + const [adventurerName, setAdventurerName] = useState(""); + const [isMaxLength, setIsMaxLength] = useState(false); + const setAdventurer = useAdventurerStore((state) => state.setAdventurer); useEffect(() => { @@ -144,6 +155,18 @@ export const AdventurerListCard = ({ setIsTransferOpen(false); }; + const handleNameChange = ( + e: ChangeEvent + ) => { + const value = e.target.value; + setAdventurerName(value.slice(0, 31)); + if (value.length >= 31) { + setIsMaxLength(true); + } else { + setIsMaxLength(false); + } + }; + return ( <> {adventurer && ( @@ -163,10 +186,18 @@ export const AdventurerListCard = ({ size={"lg"} variant={"token"} onClick={() => setIsTransferOpen(!isTransferOpen)} - className={`w-1/2 ${isTransferOpen && "animate-pulse"}`} + className={`w-1/4 ${isTransferOpen && "animate-pulse"}`} > Transfer + {isTransferOpen && ( <>
@@ -278,9 +309,46 @@ export const AdventurerListCard = ({
)} + {isEditOpen && ( + <> +
+
+ + Change Adventurer Name + +
+
+ + {isMaxLength && ( +

MAX LENGTH!

+ )} +
+ +
+
+
+ + )} )} - {isTransferOpen && ( + {(isTransferOpen || isEditOpen) && (
)} diff --git a/ui/src/app/components/start/AdventurersList.tsx b/ui/src/app/components/start/AdventurersList.tsx index 4ebf0d2aa..aecea294e 100644 --- a/ui/src/app/components/start/AdventurersList.tsx +++ b/ui/src/app/components/start/AdventurersList.tsx @@ -1,32 +1,32 @@ -import { useState, useEffect, useRef, useCallback, useMemo } from "react"; -import { - Contract, - AccountInterface, - validateAndParseAddress, - constants, -} from "starknet"; -import { StarknetIdNavigator } from "starknetid.js"; -import { useProvider } from "@starknet-react/core"; import { Button } from "@/app/components/buttons/Button"; -import useAdventurerStore from "@/app/hooks/useAdventurerStore"; import { + CartridgeIcon, + ClockIcon, CoinIcon, HeartIcon, SkullIcon, - ClockIcon, - CartridgeIcon, StarknetIdIcon, } from "@/app/components/icons/Icons"; -import useUIStore from "@/app/hooks/useUIStore"; -import { useQueriesStore } from "@/app/hooks/useQueryStore"; import LootIconLoader from "@/app/components/icons/Loader"; -import useCustomQuery from "@/app/hooks/useCustomQuery"; +import { AdventurerListCard } from "@/app/components/start/AdventurerListCard"; import { getAdventurersByOwner } from "@/app/hooks/graphql/queries"; +import useAdventurerStore from "@/app/hooks/useAdventurerStore"; +import useCustomQuery from "@/app/hooks/useCustomQuery"; import useNetworkAccount from "@/app/hooks/useNetworkAccount"; -import { indexAddress, padAddress, calculateLevel } from "@/app/lib/utils"; -import { Adventurer } from "@/app/types"; -import { AdventurerListCard } from "@/app/components/start/AdventurerListCard"; +import { useQueriesStore } from "@/app/hooks/useQueryStore"; import useTransactionCartStore from "@/app/hooks/useTransactionCartStore"; +import useUIStore from "@/app/hooks/useUIStore"; +import { calculateLevel, indexAddress, padAddress } from "@/app/lib/utils"; +import { Adventurer } from "@/app/types"; +import { useProvider } from "@starknet-react/core"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + AccountInterface, + constants, + Contract, + validateAndParseAddress, +} from "starknet"; +import { StarknetIdNavigator } from "starknetid.js"; export interface AdventurerListProps { isActive: boolean; @@ -41,6 +41,11 @@ export interface AdventurerListProps { from: string, recipient: string ) => Promise; + changeAdventurerName: ( + account: AccountInterface, + adventurerId: number, + name: string + ) => Promise; } export const AdventurersList = ({ @@ -51,6 +56,7 @@ export const AdventurersList = ({ adventurersCount, aliveAdventurersCount, transferAdventurer, + changeAdventurerName, }: AdventurerListProps) => { const { provider } = useProvider(); const starknetIdNavigator = new StarknetIdNavigator( @@ -548,6 +554,7 @@ export const AdventurersList = ({ gameContract={gameContract} handleSwitchAdventurer={handleSwitchAdventurer} transferAdventurer={transferAdventurer} + changeAdventurerName={changeAdventurerName} /> )}
diff --git a/ui/src/app/containers/AdventurerScreen.tsx b/ui/src/app/containers/AdventurerScreen.tsx index ca39b690d..2d4cece7a 100644 --- a/ui/src/app/containers/AdventurerScreen.tsx +++ b/ui/src/app/containers/AdventurerScreen.tsx @@ -35,6 +35,11 @@ interface AdventurerScreenProps { from: string, recipient: string ) => Promise; + changeAdventurerName: ( + account: AccountInterface, + adventurerId: number, + name: string + ) => Promise; } /** @@ -51,6 +56,7 @@ export default function AdventurerScreen({ mintLords, costToPlay, transferAdventurer, + changeAdventurerName, }: AdventurerScreenProps) { const [activeMenu, setActiveMenu] = useState(0); const setAdventurer = useAdventurerStore((state) => state.setAdventurer); @@ -154,6 +160,7 @@ export default function AdventurerScreen({ adventurersCount={adventurersByOwnerCount} aliveAdventurersCount={aliveAdventurersByOwnerCount} transferAdventurer={transferAdventurer} + changeAdventurerName={changeAdventurerName} /> )} diff --git a/ui/src/app/lib/utils/syscalls.ts b/ui/src/app/lib/utils/syscalls.ts index 3eab66460..62d862560 100644 --- a/ui/src/app/lib/utils/syscalls.ts +++ b/ui/src/app/lib/utils/syscalls.ts @@ -1597,6 +1597,54 @@ export function createSyscalls({ } }; + const changeAdventurerName = async ( + account: AccountInterface, + adventurerId: number, + name: string + ) => { + try { + console.log(account); + startLoading( + "Change Name", + "Changing Adventurer Name", + undefined, + undefined + ); + + const changeNameTx = { + contractAddress: gameContract?.address ?? "", + entrypoint: "update_adventurer_name", + calldata: [ + adventurerId.toString() ?? "", + stringToFelt(name).toString(), + ], + }; + + const { transaction_hash } = await account.execute([ + ...calls, + changeNameTx, + ]); + + const result = await provider.waitForTransaction(transaction_hash, { + retryInterval: getWaitRetryInterval(network!), + }); + + if (!result) { + throw new Error("Transaction did not complete successfully."); + } + + setData("adventurersByOwnerQuery", { + adventurers: [adventurer], + }); + + getBalances(); + stopLoading("Changed Adventurer Name", false, "Change Name"); + } catch (error) { + console.error(error); + stopLoading(error, true); + } + }; + return { spawn, explore, @@ -1607,6 +1655,7 @@ export function createSyscalls({ mintLords, withdraw, transferAdventurer, + changeAdventurerName, }; } diff --git a/ui/src/app/page.tsx b/ui/src/app/page.tsx index bd5e86b02..624af8e19 100644 --- a/ui/src/app/page.tsx +++ b/ui/src/app/page.tsx @@ -324,6 +324,7 @@ function Home() { mintLords, withdraw, transferAdventurer, + changeAdventurerName, } = useSyscalls({ gameContract: gameContract!, ethContract: ethContract!, @@ -833,6 +834,7 @@ function Home() { mintLords={mintLords} costToPlay={costToPlay} transferAdventurer={transferAdventurer} + changeAdventurerName={changeAdventurerName} /> )} {screen === "play" && ( From 3dcca47ea09512b87090206296536a2c210a36b8 Mon Sep 17 00:00:00 2001 From: Starknet Dev Date: Mon, 7 Oct 2024 17:28:22 +0100 Subject: [PATCH 2/7] - add check for gas - add setting of new adventurer name in list --- .../components/start/AdventurerListCard.tsx | 10 +- .../app/components/start/AdventurersList.tsx | 4 +- ui/src/app/containers/AdventurerScreen.tsx | 3 +- ui/src/app/lib/constants.ts | 4 +- ui/src/app/lib/utils/syscalls.ts | 111 +++++++++++++----- 5 files changed, 92 insertions(+), 40 deletions(-) diff --git a/ui/src/app/components/start/AdventurerListCard.tsx b/ui/src/app/components/start/AdventurerListCard.tsx index daf5eca62..fd6e6480f 100644 --- a/ui/src/app/components/start/AdventurerListCard.tsx +++ b/ui/src/app/components/start/AdventurerListCard.tsx @@ -29,8 +29,10 @@ export interface AdventurerListCardProps { changeAdventurerName: ( account: AccountInterface, adventurerId: number, - name: string + name: string, + index: number ) => Promise; + index: number; } export const AdventurerListCard = ({ @@ -39,6 +41,7 @@ export const AdventurerListCard = ({ handleSwitchAdventurer, transferAdventurer, changeAdventurerName, + index, }: AdventurerListCardProps) => { const { account, address } = useNetworkAccount(); const { provider } = useProvider(); @@ -322,7 +325,7 @@ export const AdventurerListCard = ({ type="text" value={adventurerName} onChange={handleNameChange} - className="p-1 h-12 text-2xl w-3/4 bg-terminal-black border border-terminal-green animate-pulse transform uppercase" + className="p-1 h-12 text-2xl w-3/4 bg-terminal-black border border-terminal-green animate-pulse transform" /> {isMaxLength && (

MAX LENGTH!

@@ -334,7 +337,8 @@ export const AdventurerListCard = ({ changeAdventurerName( account!, adventurer.id!, - adventurerName + adventurerName, + index ) } disabled={adventurerName === ""} diff --git a/ui/src/app/components/start/AdventurersList.tsx b/ui/src/app/components/start/AdventurersList.tsx index 54339292c..0e5fb6cc6 100644 --- a/ui/src/app/components/start/AdventurersList.tsx +++ b/ui/src/app/components/start/AdventurersList.tsx @@ -44,7 +44,8 @@ export interface AdventurerListProps { changeAdventurerName: ( account: AccountInterface, adventurerId: number, - name: string + name: string, + index: number ) => Promise; } @@ -555,6 +556,7 @@ export const AdventurersList = ({ handleSwitchAdventurer={handleSwitchAdventurer} transferAdventurer={transferAdventurer} changeAdventurerName={changeAdventurerName} + index={selectedIndex} /> )} diff --git a/ui/src/app/containers/AdventurerScreen.tsx b/ui/src/app/containers/AdventurerScreen.tsx index 00afbd7fc..e78e9f020 100644 --- a/ui/src/app/containers/AdventurerScreen.tsx +++ b/ui/src/app/containers/AdventurerScreen.tsx @@ -40,7 +40,8 @@ interface AdventurerScreenProps { changeAdventurerName: ( account: AccountInterface, adventurerId: number, - name: string + name: string, + index: number ) => Promise; } diff --git a/ui/src/app/lib/constants.ts b/ui/src/app/lib/constants.ts index 6b00b4a59..6fb8a900f 100644 --- a/ui/src/app/lib/constants.ts +++ b/ui/src/app/lib/constants.ts @@ -40,9 +40,7 @@ export const getWaitRetryInterval = (network: string) => export const ETH_INCREMENT = 0.001; export const LORDS_INCREMENT = 5; export const getMaxFee = (network: string) => - network === "mainnet" || network === "sepolia" - ? 0.3 * 10 ** 18 - : 0.03 * 10 ** 18; // 0.3ETH on mainnet or sepolia, 0.0003ETH on goerli + network === "mainnet" ? 0.001 * 10 ** 18 : 0.3 * 10 ** 18; // 0.3ETH on mainnet or sepolia, 0.0003ETH on goerli export const ETH_PREFUND_AMOUNT = (network: string) => network === "mainnet" || network === "sepolia" ? "0x2386F26FC10000" diff --git a/ui/src/app/lib/utils/syscalls.ts b/ui/src/app/lib/utils/syscalls.ts index 8bc8aec37..81a2809ab 100644 --- a/ui/src/app/lib/utils/syscalls.ts +++ b/ui/src/app/lib/utils/syscalls.ts @@ -3,7 +3,7 @@ import { QueryData, QueryKey } from "@/app/hooks/useQueryStore"; import { Network, ScreenPage } from "@/app/hooks/useUIStore"; import { AdventurerClass } from "@/app/lib/classes"; import { checkArcadeConnector } from "@/app/lib/connectors"; -import { getWaitRetryInterval } from "@/app/lib/constants"; +import { getMaxFee, getWaitRetryInterval } from "@/app/lib/constants"; import { GameData } from "@/app/lib/data/GameData"; import { DataType, @@ -1543,9 +1543,19 @@ export function createSyscalls({ ? [transferEthTx, transferLordsTx] : [transferEthTx]; - const { transaction_hash } = await account.execute(calls); + const isArcade = checkArcadeConnector(connector!); - const result = await provider.waitForTransaction(transaction_hash, { + const tx = await handleSubmitCalls( + account!, + [...calls], + isArcade, + Number(ethBalance), + showTopUpDialog, + setTopUpAccount, + network + ); + + const result = await provider.waitForTransaction(tx?.transaction_hash, { retryInterval: getWaitRetryInterval(network!), }); @@ -1576,12 +1586,19 @@ export function createSyscalls({ calldata: [from, recipient, adventurerId.toString() ?? "", "0"], }; - const { transaction_hash } = await account.execute([ - ...calls, - transferTx, - ]); + const isArcade = checkArcadeConnector(connector!); - const result = await provider.waitForTransaction(transaction_hash, { + const tx = await handleSubmitCalls( + account!, + [...calls, transferTx], + isArcade, + Number(ethBalance), + showTopUpDialog, + setTopUpAccount, + network + ); + + const result = await provider.waitForTransaction(tx?.transaction_hash, { retryInterval: getWaitRetryInterval(network!), }); @@ -1604,17 +1621,17 @@ export function createSyscalls({ const changeAdventurerName = async ( account: AccountInterface, adventurerId: number, - name: string + name: string, + index: number ) => { - try { - console.log(account); - startLoading( - "Change Name", - "Changing Adventurer Name", - undefined, - undefined - ); + startLoading( + "Change Name", + "Changing Adventurer Name", + undefined, + undefined + ); + try { const changeNameTx = { contractAddress: gameContract?.address ?? "", entrypoint: "update_adventurer_name", @@ -1624,25 +1641,55 @@ export function createSyscalls({ ], }; - const { transaction_hash } = await account.execute([ - ...calls, - changeNameTx, - ]); + const isArcade = checkArcadeConnector(connector!); - const result = await provider.waitForTransaction(transaction_hash, { - retryInterval: getWaitRetryInterval(network!), - }); + const maxFee = getMaxFee(network!); - if (!result) { - throw new Error("Transaction did not complete successfully."); - } + if (ethBalance < maxFee) { + showTopUpDialog(true); + setTopUpAccount("eth"); + throw new Error("Not enough eth for gas."); + } else { + const tx = await handleSubmitCalls( + account!, + [...calls, changeNameTx], + isArcade, + Number(ethBalance), + showTopUpDialog, + setTopUpAccount, + network + ); - setData("adventurersByOwnerQuery", { - adventurers: [adventurer], - }); + const result = await provider.waitForTransaction(tx?.transaction_hash, { + retryInterval: getWaitRetryInterval(network!), + }); - getBalances(); - stopLoading("Changed Adventurer Name", false, "Change Name"); + if (!result) { + throw new Error("Transaction did not complete successfully."); + } + + const adventurers = + queryData.adventurersByOwnerQuery?.adventurers ?? []; + + setData("adventurersByOwnerQuery", { + adventurers: [ + ...adventurers.slice(0, index), + { ...adventurers[index], name: name }, + ...adventurers.slice(index + 1), + ], + }); + + console.log({ + adventurers: [ + ...adventurers.slice(0, index), + { ...adventurers[index], name: name }, + ...adventurers.slice(index + 1), + ], + }); + + getBalances(); + stopLoading("Changed Adventurer Name", false, "Change Name"); + } } catch (error) { console.error(error); stopLoading(error, true); From aa9f001a586bc3b7acafdca44610046b6e181af3 Mon Sep 17 00:00:00 2001 From: Starknet Dev Date: Mon, 7 Oct 2024 20:52:20 +0100 Subject: [PATCH 3/7] - add setting tx hash for acivity loader - switch adventurers data to be from store --- ui/src/app/components/navigation/TxActivity.tsx | 10 +++++----- ui/src/app/components/start/AdventurerListCard.tsx | 7 ++++--- ui/src/app/components/start/AdventurersList.tsx | 6 ++++-- ui/src/app/lib/utils/syscalls.ts | 4 +++- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ui/src/app/components/navigation/TxActivity.tsx b/ui/src/app/components/navigation/TxActivity.tsx index 478e3ea15..5b0047ab2 100644 --- a/ui/src/app/components/navigation/TxActivity.tsx +++ b/ui/src/app/components/navigation/TxActivity.tsx @@ -1,12 +1,12 @@ -import { useEffect, useState } from "react"; -import { InvokeTransactionReceiptResponse } from "starknet"; -import { useWaitForTransaction } from "@starknet-react/core"; -import { displayAddress, padAddress } from "@/app/lib/utils"; -import useLoadingStore from "@/app/hooks/useLoadingStore"; import LootIconLoader from "@/app/components/icons/Loader"; +import useLoadingStore from "@/app/hooks/useLoadingStore"; import useTransactionCartStore from "@/app/hooks/useTransactionCartStore"; import useUIStore from "@/app/hooks/useUIStore"; import { networkConfig } from "@/app/lib/networkConfig"; +import { displayAddress, padAddress } from "@/app/lib/utils"; +import { useWaitForTransaction } from "@starknet-react/core"; +import { useEffect, useState } from "react"; +import { InvokeTransactionReceiptResponse } from "starknet"; export const TxActivity = () => { const stopLoading = useLoadingStore((state) => state.stopLoading); diff --git a/ui/src/app/components/start/AdventurerListCard.tsx b/ui/src/app/components/start/AdventurerListCard.tsx index fd6e6480f..4dc97f520 100644 --- a/ui/src/app/components/start/AdventurerListCard.tsx +++ b/ui/src/app/components/start/AdventurerListCard.tsx @@ -333,14 +333,15 @@ export const AdventurerListCard = ({
@@ -203,6 +213,7 @@ export const AdventurerListCard = ({ variant={"token"} onClick={() => setIsEditOpen(!isEditOpen)} className="w-1/4" + disabled={dead || expired} > Edit @@ -210,11 +221,7 @@ export const AdventurerListCard = ({ <>
-
- - Enter Address - - + + + Enter Address + +
+ setIsTransferOpen(false)} + className="w-10 h-10 cursor-pointer" + /> +
- +
+ Change Adventurer Name +
+ setIsEditOpen(false)} + className="w-10 h-10 cursor-pointer" + /> +
Save diff --git a/ui/src/app/components/start/AdventurersList.tsx b/ui/src/app/components/start/AdventurersList.tsx index eff2b1018..c15c6a9e3 100644 --- a/ui/src/app/components/start/AdventurersList.tsx +++ b/ui/src/app/components/start/AdventurersList.tsx @@ -19,7 +19,14 @@ import useUIStore from "@/app/hooks/useUIStore"; import { calculateLevel, indexAddress, padAddress } from "@/app/lib/utils"; import { Adventurer } from "@/app/types"; import { useProvider } from "@starknet-react/core"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + ChangeEvent, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; import { AccountInterface, constants, @@ -67,8 +74,12 @@ export const AdventurersList = ({ const [selectedIndex, setSelectedIndex] = useState(-1); const [showZeroHealth, setShowZeroHealth] = useState(false); const [isTransferOpen, setIsTransferOpen] = useState(false); + const [isEditOpen, setIsEditOpen] = useState(false); const [adventurerForTransfer, setAdventurerForTransfer] = useState(null); + const [adventurerForEdit, setAdventurerForEdit] = useState( + null + ); const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]); const network = useUIStore((state) => state.network); const { account, address } = useNetworkAccount(); @@ -96,6 +107,10 @@ export const AdventurersList = ({ "send" | "addToCart" | null >(null); + const [adventurerName, setAdventurerName] = useState(""); + + const [isMaxLength, setIsMaxLength] = useState(false); + const addToCalls = useTransactionCartStore((state) => state.addToCalls); const handleAddTransferTx = (recipient: string, adventurerId: number) => { @@ -270,34 +285,44 @@ export const AdventurersList = ({ setIsTransferOpen(false); }; + const handleNameChange = ( + e: ChangeEvent + ) => { + const value = e.target.value; + setAdventurerName(value.slice(0, 31)); + if (value.length >= 31) { + setIsMaxLength(true); + } else { + setIsMaxLength(false); + } + }; + return (
- {formatAdventurersCount > 0 ? ( -
-
- -

- Adventurers -

- {formatAdventurersCount > 0 && ( - - )} -
-
- {isLoading && ( -
- -
- )} -
- {!isTransferOpen ? ( +
+
+ +

+ Adventurers +

+ +
+
+ {isLoading && ( +
+ +
+ )} +
+ {formatAdventurersCount > 0 ? ( + !isTransferOpen && !isEditOpen ? ( adventurers.map((adventurer, index) => { const birthstamp = parseInt(adventurer.birthDate!); const currentTimestamp = Math.floor(Date.now() / 1000); @@ -325,6 +350,7 @@ export const AdventurersList = ({ setAdventurer(adventurer); handleSwitchAdventurer(adventurer.id!); }} + disabled={dead || expired} > Play @@ -339,6 +365,18 @@ export const AdventurersList = ({ > Transfer +
)} @@ -354,7 +392,6 @@ export const AdventurersList = ({ setSelectedIndex(index); await handleSelectAdventurer(adventurer.id!); }} - disabled={dead || expired} > {expired && !dead && (
@@ -401,7 +438,7 @@ export const AdventurersList = ({
); }) - ) : ( + ) : isTransferOpen ? (
- )} -
- {formatAdventurersCount > 10 && ( -
- - - -
+ ) : ( +
+ +
+ + Change Adventurer Name + +
+
+ + {isMaxLength && ( +

MAX LENGTH!

+ )} +
+ +
+
+
+ ) + ) : ( +

+ You do not have any adventurers! +

)}
-
-
- {isLoading ? ( -
- + {formatAdventurersCount > 10 && ( +
+ + +
- ) : ( - )}
- ) : ( -

- You do not have any adventurers! -

- )} +
+ {isLoading ? ( +
+ +
+ ) : ( + + )} +
+
); };