From ab8fe81c1afbd30cec18a0fbb0de154f40bc960a Mon Sep 17 00:00:00 2001 From: Starknet Dev <42612612+starknetdev@users.noreply.github.com> Date: Tue, 1 Oct 2024 19:07:42 -0400 Subject: [PATCH] Add support for tournament winner (#274) - add art assets - add extra pay button - hide dead adventurers by default --- ui/.env | 3 +- ui/public/blobert.png | Bin 0 -> 1189 bytes ui/public/insert-blobert-hover.png | Bin 0 -> 2793 bytes ui/public/insert-blobert.png | Bin 0 -> 3174 bytes .../components/notifications/SpecialBeast.tsx | 15 ++-- .../app/components/start/AdventurersList.tsx | 38 ++++---- .../app/components/start/CreateAdventurer.tsx | 12 ++- ui/src/app/components/start/Spawn.tsx | 85 ++++++++++++++---- ui/src/app/containers/AdventurerScreen.tsx | 4 + ui/src/app/hooks/graphql/queries.ts | 44 ++++++--- ui/src/app/lib/clients.ts | 24 ----- ui/src/app/lib/networkConfig.ts | 5 ++ ui/src/app/lib/utils/syscalls.ts | 13 +-- ui/src/app/page.tsx | 23 ++++- 14 files changed, 174 insertions(+), 92 deletions(-) create mode 100644 ui/public/blobert.png create mode 100644 ui/public/insert-blobert-hover.png create mode 100644 ui/public/insert-blobert.png diff --git a/ui/.env b/ui/.env index 51abe46d9..1060dd74f 100644 --- a/ui/.env +++ b/ui/.env @@ -1 +1,2 @@ -NEXT_PUBLIC_NETWORK="mainnet" \ No newline at end of file +NEXT_PUBLIC_NETWORK="mainnet" +NEXT_PUBLIC_TOURNAMENT_ENDED="false" \ No newline at end of file diff --git a/ui/public/blobert.png b/ui/public/blobert.png new file mode 100644 index 0000000000000000000000000000000000000000..13b9d7e880dc99373d06edd8e01960631617402b GIT binary patch literal 1189 zcmeAS@N?(olHy`uVBq!ia0vp^CxG}82OE&&7wu05Qk(@Ik;M!Q+`=Ht$S`Y;1W=H% zILO_JVcj{Imp~3nx}&cn1H;CC?mvmFK(3Xii(^Oy2~*{hS}!Hxv8i>?}5Yn7?-e!+$RY0Tw1lRN~=aPt=sMXrA1y&jDB_(RV7U0w=~hYdQUDttnkLjSd3nM9bpSeY5qRgrA!mb8U-0_s=U|KF7tU>B;FV-hX?Y{<}N@4yHy0 z3}W^A8QJ@7Yj;hUZ&_PY@@|9flihi5x1aa-6|ccz%}3*xms|f_e{UbZ&7ju$=ar4Z zuk9Y&mA>u1x#`cvr{CS5*X{Ur`Nf^5>$m^h?Ym$9@_ED3uh-tpti)m5*?aHyecOEE zvTNC{9rt(ceph5|8hhgUzwgVq|J_>lUT8+KhJZoU8MJsTF+Gc|6wdHe45IGgKn z3*zg3AHKLVJifj-@^aYuFYkXnpZkx$qnmxZ`|~|_Wy3JN4%GY$sQF)PaYfFb-`@_a z)}G=;k2r92B>wUFRpPn7?&X_JtsgI)iktl}t0DbTA}hA=oc-7DSK{YO<@fb|Kj`;qS$}|E>AC4j5tie?C3m#Q#or^ZDKS-Mgh(nj923Fo^U^^Cwon-?QVxpTcI$ zs0Sto3H_Jl@BZ0Yl|TFPv9nHyoKG(O8C_VW7&9BWLZ|$D{_DlH%9ATY5?aS7+d(W)Ty*~Y4Z2XDkcd+LV zotM^Wt6Bf=U0?Slwt@+J7_+>7S)BFu=-o;GQgC?0UHsdu);}+CgwP+}H}P|;E7U#P P7=Xaj)z4*}Q$iB}n(4}g literal 0 HcmV?d00001 diff --git a/ui/public/insert-blobert-hover.png b/ui/public/insert-blobert-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..c803a206735067ea16632c654be3cc6aa66e469a GIT binary patch literal 2793 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 literal 0 HcmV?d00001 diff --git a/ui/public/insert-blobert.png b/ui/public/insert-blobert.png new file mode 100644 index 0000000000000000000000000000000000000000..89e30b0cec173ff167fbdda9f3529fe243ce30bf GIT binary patch literal 3174 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 M07*qoM6N<$f(AtaX#fBK literal 0 HcmV?d00001 diff --git a/ui/src/app/components/notifications/SpecialBeast.tsx b/ui/src/app/components/notifications/SpecialBeast.tsx index 7c2eef350..ae5c5d5b9 100644 --- a/ui/src/app/components/notifications/SpecialBeast.tsx +++ b/ui/src/app/components/notifications/SpecialBeast.tsx @@ -1,13 +1,13 @@ -import { useState, useEffect } from "react"; import { fetchBeastImage } from "@/app/api/fetchMetadata"; -import Image from "next/image"; -import useUIStore from "@/app/hooks/useUIStore"; -import { Contract } from "starknet"; -import { processBeastName } from "@/app/lib/utils"; +import { Button } from "@/app/components/buttons/Button"; import TwitterShareButton from "@/app/components/buttons/TwitterShareButtons"; import useAdventurerStore from "@/app/hooks/useAdventurerStore"; -import { Button } from "@/app/components/buttons/Button"; +import useUIStore from "@/app/hooks/useUIStore"; import { networkConfig } from "@/app/lib/networkConfig"; +import { processBeastName } from "@/app/lib/utils"; +import Image from "next/image"; +import { useEffect, useState } from "react"; +import { Contract } from "starknet"; interface SpecialBeastProps { beastsContract: Contract; @@ -52,7 +52,8 @@ export const SpecialBeast = ({ beastsContract }: SpecialBeastProps) => { const beastUrl = (networkConfig[network!].beastsViewer ?? "") + "/" + - specialBeast?.tokenId?.toString(); + specialBeast?.tokenId?.toString() + + "?beast_origin=client"; return (
diff --git a/ui/src/app/components/start/AdventurersList.tsx b/ui/src/app/components/start/AdventurersList.tsx index 4ebf0d2aa..4aeefa544 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; @@ -58,7 +58,7 @@ export const AdventurersList = ({ constants.StarknetChainId.SN_MAIN ); const [selectedIndex, setSelectedIndex] = useState(-1); - const [showZeroHealth, setShowZeroHealth] = useState(true); + const [showZeroHealth, setShowZeroHealth] = useState(false); const [isTransferOpen, setIsTransferOpen] = useState(false); const [adventurerForTransfer, setAdventurerForTransfer] = useState(null); diff --git a/ui/src/app/components/start/CreateAdventurer.tsx b/ui/src/app/components/start/CreateAdventurer.tsx index f55892778..b72e30b19 100644 --- a/ui/src/app/components/start/CreateAdventurer.tsx +++ b/ui/src/app/components/start/CreateAdventurer.tsx @@ -1,9 +1,9 @@ -import React, { useState, useEffect, useCallback } from "react"; -import { Contract } from "starknet"; -import { FormData } from "@/app/types"; import { AdventurerName } from "@/app/components/start/AdventurerName"; -import { WeaponSelect } from "@/app/components/start/WeaponSelect"; import { Spawn } from "@/app/components/start/Spawn"; +import { WeaponSelect } from "@/app/components/start/WeaponSelect"; +import { FormData } from "@/app/types"; +import React, { useCallback, useEffect, useState } from "react"; +import { Contract } from "starknet"; export interface CreateAdventurerProps { isActive: boolean; @@ -11,6 +11,7 @@ export interface CreateAdventurerProps { spawn: (...args: any[]) => any; lordsBalance?: bigint; goldenTokenData: any; + blobertsData: any; gameContract: Contract; getBalances: () => Promise; mintLords: (lordsAmount: number) => Promise; @@ -23,6 +24,7 @@ export const CreateAdventurer = ({ spawn, lordsBalance, goldenTokenData, + blobertsData, gameContract, getBalances, mintLords, @@ -119,6 +121,7 @@ export const CreateAdventurer = ({ handleBack={handleBack} lordsBalance={lordsBalance} goldenTokenData={goldenTokenData} + blobertsData={blobertsData} gameContract={gameContract} getBalances={getBalances} mintLords={mintLords} @@ -144,6 +147,7 @@ export const CreateAdventurer = ({ handleBack={handleBack} lordsBalance={lordsBalance} goldenTokenData={goldenTokenData} + blobertsData={blobertsData} gameContract={gameContract} getBalances={getBalances} mintLords={mintLords} diff --git a/ui/src/app/components/start/Spawn.tsx b/ui/src/app/components/start/Spawn.tsx index 40d442d2a..13e0f79af 100644 --- a/ui/src/app/components/start/Spawn.tsx +++ b/ui/src/app/components/start/Spawn.tsx @@ -25,12 +25,14 @@ export interface SpawnProps { spawn: ( formData: FormData, goldenTokenId: string, + blobertTokenId: string, revenueAddresses: string[], costToPlay?: number ) => Promise; handleBack: () => void; lordsBalance?: bigint; goldenTokenData: any; + blobertsData: any; gameContract: Contract; getBalances: () => Promise; mintLords: (lordsAmount: number) => Promise; @@ -43,6 +45,7 @@ export const Spawn = ({ handleBack, lordsBalance, goldenTokenData, + blobertsData, gameContract, getBalances, mintLords, @@ -50,7 +53,8 @@ export const Spawn = ({ }: SpawnProps) => { const [paymentInitiated, setPaymentInitiated] = useState(false); const [formFilled, setFormFilled] = useState(false); - const [usableToken, setUsableToken] = useState("0"); + const [usableGoldenToken, setUsableGoldenToken] = useState("0"); + const [usableBlobertToken, setUsableBlobertToken] = useState("0"); const [isHoveringLords, setIsHoveringLords] = useState(false); const [showPaymentDetails, setShowPaymentDetails] = useState(false); const isWrongNetwork = useUIStore((state) => state.isWrongNetwork); @@ -76,6 +80,7 @@ export const Spawn = ({ await spawn( formData, "0", + "0", networkConfig[network!].revenueAddresses, lordsGameCost ); @@ -84,8 +89,8 @@ export const Spawn = ({ } }; - const tokens = goldenTokenData?.getERC721Tokens; - const goldenTokens: number[] = tokens?.map( + const goldenTokens = goldenTokenData?.getERC721Tokens; + const goldenTokenIds: number[] = goldenTokens?.map( (token: GameToken) => token.token_id ); @@ -97,7 +102,26 @@ export const Spawn = ({ CallData.compile(["0", tokenId.toString()]) ); if (canPlay) { - setUsableToken(tokenId.toString()); + setUsableGoldenToken(tokenId.toString()); + break; + } + } + }; + + const blobertTokens = blobertsData?.tokens; + const blobertTokenIds: number[] = blobertTokens?.map( + (token: any) => token.tokenId + ); + + const getUsableBlobertToken = async (tokenIds: number[]) => { + // Loop through contract calls to see if the token is usable, if none then return 0 + for (let tokenId of tokenIds) { + const canPlay = await gameContract.call( + "free_game_available", + CallData.compile(["1", tokenId.toString()]) + ); + if (canPlay) { + setUsableBlobertToken(tokenId.toString()); break; } } @@ -106,11 +130,16 @@ export const Spawn = ({ const { play: spawnPlay } = useUiSounds(soundSelector.spawn); const { play: coinPlay } = useUiSounds(soundSelector.coin); + const tournamentEnded = process.env.NEXT_PUBLIC_TOURNAMENT_ENDED === "true"; + useEffect(() => { - getUsableGoldenToken(goldenTokens ?? []); + getUsableGoldenToken(goldenTokenIds ?? []); + if (tournamentEnded) { + getUsableBlobertToken(blobertTokenIds ?? []); + } }, []); - const handlePayment = async (goldenToken: boolean) => { + const handlePayment = async (goldenToken: boolean, blobertToken: boolean) => { spawnPlay(); coinPlay(); resetNotification(); @@ -118,7 +147,8 @@ export const Spawn = ({ try { await spawn( formData, - goldenToken ? usableToken : "0", + goldenToken ? usableGoldenToken : "0", + blobertToken && tournamentEnded ? usableBlobertToken : "0", networkConfig[network!].revenueAddresses, lordsGameCost ); @@ -190,11 +220,10 @@ export const Spawn = ({ onMouseEnter={() => setIsHoveringLords(true)} onMouseLeave={() => setIsHoveringLords(false)} onClick={() => { - if (usableToken !== "0") { - handlePayment(true); - } else { - handlePayment(false); - } + handlePayment( + usableGoldenToken !== "0", + usableBlobertToken !== "0" + ); }} >
@@ -206,11 +235,19 @@ export const Spawn = ({ : "bg-terminal-green/20" }`} > - {usableToken !== "0" ? ( + {usableGoldenToken !== "0" ? ( insert-lords + + ) : usableBlobertToken !== "0" ? ( + + blobert @@ -225,10 +262,14 @@ export const Spawn = ({ )} {!paymentInitiated && ( -
- +
)}
diff --git a/ui/src/app/containers/AdventurerScreen.tsx b/ui/src/app/containers/AdventurerScreen.tsx index ca39b690d..325d45e2b 100644 --- a/ui/src/app/containers/AdventurerScreen.tsx +++ b/ui/src/app/containers/AdventurerScreen.tsx @@ -19,6 +19,7 @@ interface AdventurerScreenProps { spawn: ( formData: FormData, goldenTokenId: string, + blobertTokenId: string, revenueAddresses: string[], costToPlay?: number ) => Promise; @@ -26,6 +27,7 @@ interface AdventurerScreenProps { lordsBalance?: bigint; gameContract: Contract; goldenTokenData: any; + blobertsData: any; getBalances: () => Promise; mintLords: (lordsAmount: number) => Promise; costToPlay: bigint; @@ -47,6 +49,7 @@ export default function AdventurerScreen({ lordsBalance, gameContract, goldenTokenData, + blobertsData, getBalances, mintLords, costToPlay, @@ -136,6 +139,7 @@ export default function AdventurerScreen({ spawn={spawn} lordsBalance={lordsBalance} goldenTokenData={goldenTokenData} + blobertsData={blobertsData} gameContract={gameContract} getBalances={getBalances} mintLords={mintLords} diff --git a/ui/src/app/hooks/graphql/queries.ts b/ui/src/app/hooks/graphql/queries.ts index d64bca395..886c5d125 100644 --- a/ui/src/app/hooks/graphql/queries.ts +++ b/ui/src/app/hooks/graphql/queries.ts @@ -468,26 +468,42 @@ const getCollectionsTotals = gql` } `; +const getOwnerTokens = gql` + query getOwnerTokens($token: HexValue, $owner: HexValue) { + tokens( + where: { token: { eq: $token }, nftOwnerAddress: { eq: $owner } } + limit: 1000 + ) { + hash + nftOwnerAddress + timestamp + token + tokenId + } + } +`; + export { - getLatestDiscoveries, - getLastBeastDiscovery, + getAdventurerById, + getAdventurerCounts, + getAdventurerRank, getAdventurersByOwner, getAdventurersByOwnerCount, - getAdventurerById, getAdventurersInList, - getBeast, - getKilledBeasts, + getAliveAdventurersByXPPaginated, + getAliveAdventurersCount, getBattlesByBeast, + getBeast, + getCollectionsTotals, + getDeadAdventurersByXPPaginated, getDiscoveriesAndBattlesByAdventurerPaginated, - getLatestMarketItems, + getDiscoveryBattleCount, + getGoldenTokensByOwner, getItemsByAdventurer, - getDeadAdventurersByXPPaginated, - getAliveAdventurersByXPPaginated, + getKilledBeasts, + getLastBeastDiscovery, + getLatestDiscoveries, + getLatestMarketItems, + getOwnerTokens, getScoresInList, - getGoldenTokensByOwner, - getAdventurerCounts, - getAliveAdventurersCount, - getDiscoveryBattleCount, - getAdventurerRank, - getCollectionsTotals, }; diff --git a/ui/src/app/lib/clients.ts b/ui/src/app/lib/clients.ts index 78bc632cf..ee4642755 100644 --- a/ui/src/app/lib/clients.ts +++ b/ui/src/app/lib/clients.ts @@ -1,18 +1,4 @@ import { ApolloClient, InMemoryCache } from "@apollo/client"; -// import { setContext } from "@apollo/client/link/context"; -// import { Network } from "@/app/hooks/useUIStore"; - -// const createAuthLink = () => -// setContext((_, { headers }) => { -// return { -// headers: { -// ...headers, -// "Cache-Control": "no-cache, no-store, must-revalidate", -// Pragma: "no-cache", -// Expires: "0", -// }, -// }; -// }); export const goldenTokenClient = (GQLUrl: string) => { return new ApolloClient({ @@ -36,16 +22,6 @@ export const goldenTokenClient = (GQLUrl: string) => { }; export const gameClient = (GQLUrl: string) => { - // const httpLink = createHttpLink({ - // uri: `/api/graphql-proxy?api=${network}`, - // fetchOptions: { - // next: { revalidate: 0 }, - // cache: "no-store", - // }, - // }); - - // const authLink = createAuthLink(); - return new ApolloClient({ uri: GQLUrl, defaultOptions: { diff --git a/ui/src/app/lib/networkConfig.ts b/ui/src/app/lib/networkConfig.ts index 55cfa537e..698a0d77d 100644 --- a/ui/src/app/lib/networkConfig.ts +++ b/ui/src/app/lib/networkConfig.ts @@ -14,6 +14,7 @@ export const networkConfig = { "0x041b6ffc02ce30c6e941f1b34244ef8af0b3e8a70f5528476a7a68765afd6b39", goldenTokenAddress: "0x07626660faba349aad9ad2aaa0ff8645c079fa8e043a168d640d92472806eeac", + tournamentWinnerAddress: "0x0", revenueAddresses: [ "0x0314924118945405ac0bcd6181457712795c0effc29d8dd3be86d3f3ec62adc1", ], @@ -45,6 +46,8 @@ export const networkConfig = { "0x0158160018d590d93528995b340260e65aedd76d28a686e9daa5c4e8fad0c5dd", goldenTokenAddress: "0x04f5e296c805126637552cf3930e857f380e7c078e8f00696de4fc8545356b1d", + tournamentWinnerAddress: + "0x00539f522b29ae9251dbf7443c7a950cf260372e69efab3710a11bf17a9599f1", revenueAddresses: [ "0x036cE487952f25878a0158bA4A0C2Eb5eb66f0282567163a4B893A0EA5847D2d", "0x0616E6a5F9b1f86a0Ece6E965B2f3b27E3D784be79Cb2F6304D92Db100C7D29E", @@ -77,6 +80,7 @@ export const networkConfig = { lordsAddress: "0x0", beastsAddress: "0x0", goldenTokenAddress: "0x0", + tournamentWinnerAddress: "0x0", revenueAddresses: ["0x0"], pragmaAddress: "0x0", rendererAddress: "0x0", @@ -105,6 +109,7 @@ export const networkConfig = { lordsAddress: "0x0", beastsAddress: "0x0", goldenTokenAddress: "0x0", + tournamentWinnerAddress: "0x0", revenueAddresses: ["0x0"], pragmaAddress: "0x0", rendererAddress: "0x0", diff --git a/ui/src/app/lib/utils/syscalls.ts b/ui/src/app/lib/utils/syscalls.ts index 1772e5245..e45a0d385 100644 --- a/ui/src/app/lib/utils/syscalls.ts +++ b/ui/src/app/lib/utils/syscalls.ts @@ -411,7 +411,8 @@ export function createSyscalls({ dollarPrice: bigint, freeVRF: boolean, costToPlay?: number, - goldenTokenId?: string + goldenTokenId?: string, + blobertTokenId?: string ) => [ ...(freeVRF ? [] @@ -426,7 +427,7 @@ export function createSyscalls({ ], }, ]), - ...(goldenTokenId === "0" + ...(goldenTokenId === "0" && blobertTokenId === "0" ? [ { contractAddress: lordsContract?.address ?? "", @@ -450,6 +451,7 @@ export function createSyscalls({ const spawn = async ( formData: FormData, goldenTokenId: string, + blobertTokenId: string, revenueAddresses: string[], costToPlay?: number ) => { @@ -466,7 +468,7 @@ export function createSyscalls({ goldenTokenId, "0", // delay_stat_reveal rendererContractAddress, - "0", + blobertTokenId, "0", ], }; @@ -482,7 +484,7 @@ export function createSyscalls({ if (!enoughEth && !freeVRF) { return handleInsufficientFunds("eth"); } - if (!enoughLords && goldenTokenId === "0") { + if (!enoughLords && goldenTokenId === "0" && blobertTokenId === "0") { return handleInsufficientFunds("lords"); } @@ -491,7 +493,8 @@ export function createSyscalls({ dollarPrice, freeVRF, costToPlay, - goldenTokenId + goldenTokenId, + blobertTokenId ); } diff --git a/ui/src/app/page.tsx b/ui/src/app/page.tsx index ef0a7ec25..2de3cb5a3 100644 --- a/ui/src/app/page.tsx +++ b/ui/src/app/page.tsx @@ -39,6 +39,7 @@ import { getLastBeastDiscovery, getLatestDiscoveries, getLatestMarketItems, + getOwnerTokens, } from "@/app/hooks/graphql/queries"; import useAdventurerStore from "@/app/hooks/useAdventurerStore"; import useControls from "@/app/hooks/useControls"; @@ -51,7 +52,7 @@ import useTransactionCartStore from "@/app/hooks/useTransactionCartStore"; import useTransactionManager from "@/app/hooks/useTransactionManager"; import useUIStore, { ScreenPage } from "@/app/hooks/useUIStore"; import { fetchBalances, fetchEthBalance } from "@/app/lib/balances"; -import { goldenTokenClient } from "@/app/lib/clients"; +import { gameClient, goldenTokenClient } from "@/app/lib/clients"; import { VRF_WAIT_TIME } from "@/app/lib/constants"; import { networkConfig } from "@/app/lib/networkConfig"; import { @@ -473,6 +474,11 @@ function Home() { }; }, [address]); + const gameClientInstance = useMemo( + () => gameClient(networkConfig[network!].lsGQLURL), + [network] + ); + const goldenTokenClientInstance = useMemo( () => goldenTokenClient(networkConfig[network!].tokensGQLURL), [network] @@ -483,6 +489,20 @@ function Home() { variables: goldenTokenVariables, }); + const blobertTokenVariables = useMemo(() => { + return { + token: indexAddress( + networkConfig[network!].tournamentWinnerAddress.toLowerCase() + ), + owner: indexAddress(address ?? "").toLowerCase(), + }; + }, [address, network]); + + const { data: blobertsData } = useQuery(getOwnerTokens, { + client: gameClientInstance, + variables: blobertTokenVariables, + }); + const handleSwitchAdventurer = useCallback( async (adventurerId: number) => { setIsLoading(); @@ -871,6 +891,7 @@ function Home() { lordsBalance={lordsBalance} gameContract={gameContract!} goldenTokenData={goldenTokenData} + blobertsData={blobertsData} getBalances={getBalances} mintLords={mintLords} costToPlay={costToPlay}