From d69eefef5f558135b50473ed3b6e01b98837a2f4 Mon Sep 17 00:00:00 2001 From: Starknet Dev Date: Mon, 9 Sep 2024 15:58:35 -0400 Subject: [PATCH] add cartridge and starkid resolvers for transferring adventurers --- ui/package.json | 1 + ui/public/icons/starknet-id.svg | 35 +++++ ui/src/app/components/icons/Icons.tsx | 3 + .../components/start/AdventurerListCard.tsx | 131 +++++++++++++++--- .../CollectionsLeaderboardScreen.tsx | 13 +- ui/src/app/lib/constants.ts | 2 + ui/yarn.lock | 18 +-- 7 files changed, 164 insertions(+), 39 deletions(-) create mode 100644 ui/public/icons/starknet-id.svg diff --git a/ui/package.json b/ui/package.json index 651381bb4..b68fced50 100644 --- a/ui/package.json +++ b/ui/package.json @@ -42,6 +42,7 @@ "react-transition-group": "^4.4.5", "react-type-animation": "^3.0.1", "starknet": "6.7.0", + "starknetid.js": "^4.0.1", "starknetkit": "^1.1.9", "tailwind-merge": "^1.10.0", "tailwindcss": "^3.3.0", diff --git a/ui/public/icons/starknet-id.svg b/ui/public/icons/starknet-id.svg new file mode 100644 index 000000000..b52f582fb --- /dev/null +++ b/ui/public/icons/starknet-id.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/src/app/components/icons/Icons.tsx b/ui/src/app/components/icons/Icons.tsx index 7b94940b8..ac1b2dff2 100644 --- a/ui/src/app/components/icons/Icons.tsx +++ b/ui/src/app/components/icons/Icons.tsx @@ -59,6 +59,7 @@ import Cartridge from "public/icons/cartridge.svg"; import PotionArrow from "public/icons/potion-arrow.svg"; import Eye from "public/icons/eye.svg"; import Clock from "public/icons/clock.svg"; +import StarknetId from "public/icons/starknet-id.svg"; const ClothIcon = Cloth; const HideIcon = Hide; @@ -122,6 +123,7 @@ const SettingsIcon = Settings; const CompleteIcon = Complete; const CartridgeIcon = Cartridge; +const StarknetIdIcon = StarknetId; export { ClothIcon, @@ -184,4 +186,5 @@ export { QuestionMarkIcon, CompleteIcon, CartridgeIcon, + StarknetIdIcon, }; diff --git a/ui/src/app/components/start/AdventurerListCard.tsx b/ui/src/app/components/start/AdventurerListCard.tsx index 6ce78044b..38be5d475 100644 --- a/ui/src/app/components/start/AdventurerListCard.tsx +++ b/ui/src/app/components/start/AdventurerListCard.tsx @@ -1,13 +1,19 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Button } from "@/app/components/buttons/Button"; import { Adventurer } from "@/app/types"; import Info from "@/app/components/adventurer/Info"; -import { Contract, validateAndParseAddress } from "starknet"; +import { + AccountInterface, + Contract, + validateAndParseAddress, + constants, +} from "starknet"; import useTransactionCartStore from "@/app/hooks/useTransactionCartStore"; -import { useAccount } from "@starknet-react/core"; +import { useAccount, useProvider } from "@starknet-react/core"; import useAdventurerStore from "@/app/hooks/useAdventurerStore"; import { padAddress } from "@/app/lib/utils"; -import { AccountInterface } from "starknet"; +import { StarknetIdNavigator } from "starknetid.js"; +import { CartridgeIcon, StarknetIdIcon } from "../icons/Icons"; export interface AdventurerListCardProps { adventurer: Adventurer; @@ -28,22 +34,64 @@ export const AdventurerListCard = ({ transferAdventurer, }: AdventurerListCardProps) => { const { account, address } = useAccount(); + const { provider } = useProvider(); + const starknetIdNavigator = new StarknetIdNavigator( + provider, + constants.StarknetChainId.SN_MAIN + ); const [isTransferOpen, setIsTransferOpen] = useState(false); const [transferAddress, setTransferAddress] = useState(""); + const [validAddress, setValidAddress] = useState(false); + const [subdomain, setSubdomain] = useState(".ctrl"); + const [resolvedAddresses, setResolvedAddresses] = useState({ + ctrl: null, + starknetId: null, + }); const setAdventurer = useAdventurerStore((state) => state.setAdventurer); - const validAddress = (() => { - const paddedAddress = padAddress(transferAddress.toLowerCase()); - if (paddedAddress.length !== 66 || !transferAddress.startsWith("0x")) { - return false; - } - try { - return validateAndParseAddress(paddedAddress); - } catch { - return false; - } - })(); + useEffect(() => { + const validateAddress = async () => { + try { + // Try to resolve Starknet ID with .ctrl + const ctrlId = transferAddress + ".ctrl.stark"; + const ctrlAddress = await starknetIdNavigator.getAddressFromStarkName( + ctrlId + ); + + // Try to resolve Starknet ID without subdomain + const starknetId = transferAddress + ".stark"; + const starknetIdAddress = + await starknetIdNavigator.getAddressFromStarkName(starknetId); + + setResolvedAddresses({ + ctrl: ctrlAddress || null, + starknetId: starknetIdAddress || null, + }); + + // Set validAddress based on the current subdomain + if (subdomain === ".ctrl" && ctrlAddress) { + setValidAddress(ctrlAddress); + } else if (subdomain === "" && starknetIdAddress) { + setValidAddress(starknetIdAddress); + } else { + // If not a Starknet ID, validate as a regular address + const paddedAddress = padAddress(transferAddress.toLowerCase()); + if (paddedAddress.length === 66 && transferAddress.startsWith("0x")) { + const parsedAddress = validateAndParseAddress(paddedAddress); + setValidAddress(parsedAddress); + } else { + setValidAddress(false); + } + } + } catch { + setValidAddress(false); + setResolvedAddresses({ ctrl: null, starknetId: null }); + } + }; + + validateAddress(); + }, [transferAddress, subdomain, starknetIdNavigator]); const addToCalls = useTransactionCartStore((state) => state.addToCalls); @@ -82,7 +130,44 @@ export const AdventurerListCard = ({ {isTransferOpen && ( <>
- Enter Address +
+
+ + Enter Address + + + + + +
diff --git a/ui/src/app/lib/constants.ts b/ui/src/app/lib/constants.ts index e05d94971..7eb380881 100644 --- a/ui/src/app/lib/constants.ts +++ b/ui/src/app/lib/constants.ts @@ -117,3 +117,5 @@ export const collectionData = [ token: "0x07ae27a31bb6526e3de9cf02f081f6ce0615ac12a6d7b85ee58b8ad7947a2809", }, ]; + +export const maxGamesPlayable = 1600; diff --git a/ui/yarn.lock b/ui/yarn.lock index bafead137..3c7c5bb04 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -3984,15 +3984,10 @@ camelcase@^6.2.0: resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464: - version "1.0.30001570" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz" - integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== - -caniuse-lite@^1.0.30001629: - version "1.0.30001640" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz#32c467d4bf1f1a0faa63fc793c2ba81169e7652f" - integrity sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA== +caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001629: + version "1.0.30001659" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001659.tgz" + integrity sha512-Qxxyfv3RdHAfJcXelgf0hU4DFUVXBGTjqrBUZLUh8AtlGnsDo+CnncYtTd95+ZKfnANUOzxyIQCuU/UeBZBYoA== cardinal@^2.1.1: version "2.1.1" @@ -7681,6 +7676,11 @@ starknet@^6.11.0: ts-mixer "^6.0.3" url-join "^4.0.1" +starknetid.js@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/starknetid.js/-/starknetid.js-4.0.1.tgz#f0be98d43d073eca495f17fb3143bdca2034ef79" + integrity sha512-0Zy+MOAc5v8VMJYdvBpQVse0jbImh9KZqFLG6ekRWlOVykwN/khk99iR0WVdzdN5IUVYV1CNQizjWY5utkpO3w== + starknetkit@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/starknetkit/-/starknetkit-1.1.9.tgz#92ff7536b2bdc36017e4b16067f4c5ba264b4981"