From 77adb29214cfc0d91e03196b73869cee3807a79e Mon Sep 17 00:00:00 2001 From: loothero Date: Fri, 31 Jul 2026 19:50:20 -0700 Subject: [PATCH 1/8] Add the Beasts TypeScript SDK and the self-service registration app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR 5 of the community-beasts series: the artist-facing half of the permissionless registry. SDK (`sdk/`) - 116-bit token ID codec with BigInt, enforcing the same ranges the contract does — including the affix-pair rule, so an encoded ID can never decode into a different Beast than the one passed in. - Genesis species resolve fully offline. Tier and type are formulas, not tables; only the name and art of *community* species need a chain read, and both cache per species. - Client-side mirrors of the contract's name and art guards, so the UI can fail fast instead of failing a transaction. - `BeastsClient` returns Call objects rather than sending them, leaving the signing strategy to the caller. Name tables are generated from beast_definitions.cairo rather than transcribed (`scripts/gen-tables.mjs`): a hand-copied list of 75 species drifts silently, and a wrong species name is a wrong NFT. App (`app/`) - Register: four art variants (which one a Beast shows is decided by its token ID, so a partial set is not a species), name/type/tier/minter, one transaction. Art is checked against the contract's rules *and* decoded by the browser — a file that will not decode renders broken for every holder. - Manage: art replacement, minter rotation/pause/lock, art lock, stats source, artist transfer, custom provider swap. - The Cartridge session pre-approves management entrypoints but deliberately not registration, which mints a provenance token and permanently assigns a species ID. Tests - 50 SDK unit tests, anchored on two token IDs produced by the deployed contract rather than by this SDK, so a Cairo/TS layout drift fails. - 7 opt-in live tests proving the client's calldata and ABI decoding match the deployed contracts. - A headless smoke test driving the built app against Sepolia. Co-Authored-By: Claude Opus 5 (1M context) --- .gitignore | 4 +- app/.gitignore | 3 + app/README.md | 68 + app/index.html | 12 + app/package.json | 30 + app/scripts/smoke.mjs | 50 + app/src/App.tsx | 163 + app/src/components/ArtUpload.tsx | 74 + app/src/components/CardPreview.tsx | 84 + app/src/components/Dashboard.tsx | 302 ++ app/src/components/RegisterForm.tsx | 243 ++ app/src/lib/art.ts | 109 + app/src/lib/chain.ts | 48 + app/src/main.tsx | 25 + app/src/styles.css | 552 +++ app/src/vite-env.d.ts | 11 + app/tsconfig.json | 17 + app/vite.config.ts | 6 + package.json | 12 + pnpm-lock.yaml | 5924 +++++++++++++++++++++++++++ pnpm-workspace.yaml | 3 + scripts/gen-tables.mjs | 79 + sdk/.gitignore | 2 + sdk/README.md | 92 + sdk/package.json | 30 + sdk/src/index.ts | 52 + sdk/src/registry.ts | 319 ++ sdk/src/species.ts | 75 + sdk/src/tables.ts | 50 + sdk/src/tokenId.ts | 185 + sdk/src/types.ts | 59 + sdk/src/validation.ts | 151 + sdk/test/live.test.ts | 80 + sdk/test/species.test.ts | 104 + sdk/test/tokenId.test.ts | 172 + sdk/test/validation.test.ts | 122 + sdk/tsconfig.build.json | 7 + sdk/tsconfig.json | 15 + sdk/vitest.config.ts | 7 + 39 files changed, 9340 insertions(+), 1 deletion(-) create mode 100644 app/.gitignore create mode 100644 app/README.md create mode 100644 app/index.html create mode 100644 app/package.json create mode 100644 app/scripts/smoke.mjs create mode 100644 app/src/App.tsx create mode 100644 app/src/components/ArtUpload.tsx create mode 100644 app/src/components/CardPreview.tsx create mode 100644 app/src/components/Dashboard.tsx create mode 100644 app/src/components/RegisterForm.tsx create mode 100644 app/src/lib/art.ts create mode 100644 app/src/lib/chain.ts create mode 100644 app/src/main.tsx create mode 100644 app/src/styles.css create mode 100644 app/src/vite-env.d.ts create mode 100644 app/tsconfig.json create mode 100644 app/vite.config.ts create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 scripts/gen-tables.mjs create mode 100644 sdk/.gitignore create mode 100644 sdk/README.md create mode 100644 sdk/package.json create mode 100644 sdk/src/index.ts create mode 100644 sdk/src/registry.ts create mode 100644 sdk/src/species.ts create mode 100644 sdk/src/tables.ts create mode 100644 sdk/src/tokenId.ts create mode 100644 sdk/src/types.ts create mode 100644 sdk/src/validation.ts create mode 100644 sdk/test/live.test.ts create mode 100644 sdk/test/species.test.ts create mode 100644 sdk/test/tokenId.test.ts create mode 100644 sdk/test/validation.test.ts create mode 100644 sdk/tsconfig.build.json create mode 100644 sdk/tsconfig.json create mode 100644 sdk/vitest.config.ts diff --git a/.gitignore b/.gitignore index 00703a3..0343544 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ snfoundry_cache/ .env accounts/ .snfoundry_cache/ -coverage/ \ No newline at end of file +coverage/ +node_modules/ +dist/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..4bf964e --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +dist/ +*.png diff --git a/app/README.md b/app/README.md new file mode 100644 index 0000000..1d4d1c3 --- /dev/null +++ b/app/README.md @@ -0,0 +1,68 @@ +# Add a Beast + +Self-service web app for adding a species to the bestiary. Upload pixel art, +name it, choose where it can be minted — one transaction, no permission needed. + +```bash +pnpm install +pnpm build:sdk # the app consumes the SDK's build output +pnpm dev:app +``` + +## Configuration + +Defaults point at the Sepolia deployment in `docs/sepolia-v3-deployment.md`. +Override with a `.env`: + +``` +VITE_STARKNET_RPC_URL=https://api.cartridge.gg/x/starknet/sepolia +VITE_BEASTS_NFT=0x... +VITE_BEASTS_REGISTRY=0x... +``` + +## What the app does + +**Register.** Four art variants are required — which one a Beast shows is +decided by the shiny and animated bits in its token ID, so a species cannot ship +a partial set. Art is validated client-side against the same rules the contract +enforces (media type, base64 structure, PNG/GIF magic bytes) *and* decoded by +the browser, because a file that will not decode here renders broken for every +holder. Registration mints the artist's Genesis Beast in the same transaction. + +**Manage.** Per-species controls: replace art, rotate or pause the minter, lock +either one permanently, opt into kill stats, transfer the artist role, or +graduate to a custom art provider. Everything is artist-only on-chain; the UI +hides what the caller cannot do and the contract is the real gate. + +## The preview card is an approximation + +`CardPreview` mirrors the layout of the on-chain SVG so an artist can judge +their work in context before paying for a transaction. It is **not** the +contract's renderer — that lives in `src/beast_svg.cairo` and only produces +output once a species exists. Porting it byte-for-byte to TypeScript would let +the preview be exact; until then, treat the card as indicative and `token_uri` +as the truth. + +## Session policy + +The Cartridge connector pre-approves the registry's *management* entrypoints, so +an artist signs once and can then iterate without a popup per change. +`register_beast_with_art` is deliberately excluded: it mints a provenance token +and permanently assigns a species ID, so it should always be an explicit +signature. + +## Smoke test + +`scripts/smoke.mjs` drives the built app in headless Chromium against the live +deployment — it checks the chain read renders, name validation rejects an +injection attempt, the preview derives power correctly, and the dashboard loads +a real species. + +```bash +pnpm build && pnpm preview & +node scripts/smoke.mjs +``` + +It needs a Playwright browser; in this dev container that means +`LD_LIBRARY_PATH=/workspace/.playwright-libs/root/usr/lib/x86_64-linux-gnu` and +an `executablePath` pointing at the cached Chromium. diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000..6d78a75 --- /dev/null +++ b/app/index.html @@ -0,0 +1,12 @@ + + + + + + Add a Beast — onchain bestiary + + +
+ + + diff --git a/app/package.json b/app/package.json new file mode 100644 index 0000000..0bd5e2d --- /dev/null +++ b/app/package.json @@ -0,0 +1,30 @@ +{ + "name": "@provable-games/beasts-app", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "preview": "vite preview", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@cartridge/connector": "^0.13.12", + "@cartridge/controller": "^0.13.12", + "@provable-games/beasts-sdk": "workspace:*", + "@starknet-react/chains": "5.0.3", + "@starknet-react/core": "^5.0.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "starknet": "9.4.2" + }, + "devDependencies": { + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@vitejs/plugin-react": "^4.3.0", + "playwright": "^1.62.1", + "typescript": "^5.8.3", + "vite": "^5.4.0" + } +} diff --git a/app/scripts/smoke.mjs b/app/scripts/smoke.mjs new file mode 100644 index 0000000..6603a8c --- /dev/null +++ b/app/scripts/smoke.mjs @@ -0,0 +1,50 @@ +import { chromium } from 'playwright'; + +const browser = await chromium.launch({ + executablePath: + '/home/ubuntu/.cache/ms-playwright/chromium_headless_shell-1228/chrome-headless-shell-linux64/chrome-headless-shell', +}); +const page = await browser.newPage({ viewport: { width: 1280, height: 1400 } }); +const errors = []; +page.on('console', (m) => { if (m.type() === 'error') errors.push(m.text()); }); +page.on('pageerror', (e) => errors.push(`pageerror: ${e.message}`)); + +await page.goto('http://localhost:4173/', { waitUntil: 'domcontentloaded' }); +await page.waitForTimeout(5000); + +console.log('H1:', await page.textContent('h1')); +const body = await page.textContent('body'); +const m = body.match(/(\d+) species in the bestiary so far/); +console.log('LIVE CHAIN READ:', m ? m[0] : 'FAILED — no species count rendered'); +console.log('art slots:', await page.locator('.art-slot').count()); +console.log('preview card:', await page.locator('.card').count()); + +// Client-side name validation, no wallet needed. +await page.fill('input[placeholder="Gloomfang"]', 'bad"name'); +await page.waitForTimeout(200); +console.log('rejects injection name:', JSON.stringify(await page.locator('.field__error').first().textContent())); + +await page.fill('input[placeholder="Gloomfang"]', 'Gloomfang'); +await page.waitForTimeout(200); +console.log('accepts valid name — card title:', JSON.stringify(await page.textContent('.card__title'))); + +// Tier drives the power number on the preview card. +await page.selectOption('select >> nth=1', '1'); +await page.waitForTimeout(200); +const power = await page.locator('.stat', { hasText: 'Power' }).textContent(); +console.log('tier 1 power (level 10 x 5):', JSON.stringify(power)); + +await page.screenshot({ path: 'smoke-register.png', fullPage: true }); + +// Dashboard for the live species 76. +await page.fill('input[placeholder="Species #"]', '76'); +await page.click('.lookup button'); +await page.waitForTimeout(5000); +console.log('dashboard heading:', JSON.stringify(await page.textContent('.dashboard__header h2').catch(() => null))); +console.log('dashboard meta:', JSON.stringify(await page.textContent('.dashboard__header p').catch(() => null))); +console.log('badges:', await page.locator('.badge').allTextContents()); +console.log('read-only notice:', JSON.stringify(await page.textContent('.notice').catch(() => null))); +await page.screenshot({ path: 'smoke-dashboard.png', fullPage: true }); + +console.log('CONSOLE ERRORS:', errors.length ? errors.slice(0, 4) : 'none'); +await browser.close(); diff --git a/app/src/App.tsx b/app/src/App.tsx new file mode 100644 index 0000000..9d55972 --- /dev/null +++ b/app/src/App.tsx @@ -0,0 +1,163 @@ +import { useAccount, useConnect, useDisconnect } from '@starknet-react/core'; +import { + BeastsClient, + FIRST_COMMUNITY_ID, + type BeastDefinition, +} from '@provable-games/beasts-sdk'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { ADDRESSES, provider } from './lib/chain'; +import { Dashboard } from './components/Dashboard'; +import { RegisterForm, type RegistrationInput } from './components/RegisterForm'; + +type View = { kind: 'register' } | { kind: 'species'; id: bigint }; + +export function App() { + const { address, account } = useAccount(); + const { connect, connectors } = useConnect(); + const { disconnect } = useDisconnect(); + + const [view, setView] = useState({ kind: 'register' }); + const [submitting, setSubmitting] = useState(false); + const [error, setError] = useState(); + const [definition, setDefinition] = useState(null); + const [speciesCount, setSpeciesCount] = useState(null); + const [lookup, setLookup] = useState(''); + + const client = useMemo( + () => new BeastsClient(provider(), ADDRESSES, account), + [account], + ); + + const refresh = useCallback(async () => { + setSpeciesCount(await client.speciesCount().catch(() => null)); + if (view.kind !== 'species') { + setDefinition(null); + return; + } + try { + setDefinition(await client.getDefinition(view.id)); + setError(undefined); + } catch { + setDefinition(null); + setError(`Species ${view.id} is not registered`); + } + }, [client, view]); + + useEffect(() => { + void refresh(); + }, [refresh]); + + async function register(input: RegistrationInput) { + setSubmitting(true); + setError(undefined); + try { + const before = await client.speciesCount(); + await client.execute( + client.registerWithArtCall({ + name: input.name, + beastType: input.beastType, + tier: input.tier, + minter: input.minter, + art: input.art, + }), + ); + // species_count counts genesis too, so the new ID is the old count + 1. + setView({ kind: 'species', id: before + 1n }); + } catch (e) { + setError(e instanceof Error ? e.message : String(e)); + } finally { + setSubmitting(false); + } + } + + const isArtist = + !!address && !!definition && BigInt(definition.artist) === BigInt(address); + + return ( +
+
+ + +
+
{ + e.preventDefault(); + const id = BigInt(lookup || '0'); + if (id >= FIRST_COMMUNITY_ID) setView({ kind: 'species', id }); + }} + > + setLookup(e.target.value.replace(/\D/g, ''))} + /> + +
+ + {address ? ( + + ) : ( + + )} +
+
+ +
+ {view.kind === 'register' ? ( + <> +
+

Put your Beast onchain

+

+ Anyone can add a species to the bestiary. Upload pixel art, name + it, pick where it lives — one transaction, no permission needed. + You keep the Genesis Beast: the creator's token, one per species, + forever. +

+ {speciesCount !== null && ( +

+ {speciesCount.toString()} species in the bestiary so far. +

+ )} +
+ + + ) : definition ? ( + void refresh()} + /> + ) : ( +
+

{error ?? 'Loading…'}

+ +
+ )} +
+ +
+ + Registry {shortAddr(ADDRESSES.registry)} · Collection{' '} + {shortAddr(ADDRESSES.nft)} + +
+
+ ); +} + +function shortAddr(address: string): string { + const hex = BigInt(address).toString(16); + return `0x${hex.slice(0, 6)}…${hex.slice(-4)}`; +} diff --git a/app/src/components/ArtUpload.tsx b/app/src/components/ArtUpload.tsx new file mode 100644 index 0000000..44b9df2 --- /dev/null +++ b/app/src/components/ArtUpload.tsx @@ -0,0 +1,74 @@ +import { useState } from 'react'; +import { ART_SLOTS, ArtLoadError, loadArtFile, type ArtSlot, type LoadedArt } from '../lib/art'; + +interface Props { + loaded: Partial>; + onChange: (slot: ArtSlot, art: LoadedArt | undefined) => void; + onSelect: (slot: ArtSlot) => void; + selected: ArtSlot; + disabled?: boolean; +} + +export function ArtUpload({ loaded, onChange, onSelect, selected, disabled }: Props) { + const [errors, setErrors] = useState>>({}); + + async function handleFile(slot: ArtSlot, kind: 'png' | 'gif', file: File | undefined) { + if (!file) return; + setErrors((e) => ({ ...e, [slot]: undefined })); + try { + const art = await loadArtFile(file, kind); + onChange(slot, art); + onSelect(slot); + } catch (error) { + const message = + error instanceof ArtLoadError ? error.message : 'Could not process that file'; + setErrors((e) => ({ ...e, [slot]: message })); + onChange(slot, undefined); + } + } + + return ( +
+ {ART_SLOTS.map(({ slot, label, hint, kind, accept }) => { + const art = loaded[slot]; + const error = errors[slot]; + return ( +
art && onSelect(slot)} + > +
+ {label} + {kind.toUpperCase()} +
+ + + +

{hint}

+ {art && ( +

+ {(art.bytes / 1024).toFixed(1)} KB · {art.slots.toLocaleString()} slots +

+ )} + {error &&

{error}

} +
+ ); + })} +
+ ); +} diff --git a/app/src/components/CardPreview.tsx b/app/src/components/CardPreview.tsx new file mode 100644 index 0000000..91dde9d --- /dev/null +++ b/app/src/components/CardPreview.tsx @@ -0,0 +1,84 @@ +import { BEAST_TYPE_NAMES, BeastType, prefixName, suffixName } from '@provable-games/beasts-sdk'; + +interface Props { + name: string; + tier: number; + beastType: BeastType; + art?: string; + shiny: boolean; + /** Sample affixes, so the artist can see how a named variant reads. */ + prefix: number; + suffix: number; + level: number; + health: number; +} + +/** + * Approximation of the card the contract renders. + * + * This is NOT the on-chain SVG — that is built by `src/beast_svg.cairo` and + * only exists once a species is registered. This preview mirrors its layout + * and the values it derives so an artist can judge their art in context + * before paying for a transaction. After registration the app shows the real + * `token_uri` output instead. + */ +export function CardPreview({ + name, + tier, + beastType, + art, + shiny, + prefix, + suffix, + level, + health, +}: Props) { + const power = level * (6 - tier); + const displayName = + prefix > 0 && suffix > 0 + ? `"${prefixName(prefix)} ${suffixName(suffix)}" ${name || 'Unnamed'}` + : name || 'Unnamed'; + + return ( +
+
+ {displayName} +
+ +
+ {art ? ( + {`${name} + ) : ( +
Upload art to preview
+ )} +
+ +
+ + + +
+ +
+ + + +
+ +

+ Preview only — the collection renders this card fully onchain. + {prefix > 0 && ' Affixes shown are a sample: every mint draws its own.'}{' '} + Ranks and kill stats appear once a Beast is minted. +

+
+ ); +} + +function Stat({ label, value }: { label: string; value: string }) { + return ( +
+
{label}
+
{value}
+
+ ); +} diff --git a/app/src/components/Dashboard.tsx b/app/src/components/Dashboard.tsx new file mode 100644 index 0000000..45bf5f1 --- /dev/null +++ b/app/src/components/Dashboard.tsx @@ -0,0 +1,302 @@ +import { + BEAST_TYPE_NAMES, + type BeastDefinition, + type BeastsClient, +} from '@provable-games/beasts-sdk'; +import { useState } from 'react'; +import { ART_SLOTS, loadArtFile, type ArtSlot, type LoadedArt } from '../lib/art'; + +interface Props { + beastId: bigint; + definition: BeastDefinition; + client: BeastsClient; + isArtist: boolean; + onChanged: () => void; +} + +const ZERO = '0x0'; + +/** + * Per-species controls. Every action here is artist-only on-chain; the UI + * simply hides what the caller cannot do, and the contract is the real gate. + */ +export function Dashboard({ beastId, definition, client, isArtist, onChanged }: Props) { + const [busy, setBusy] = useState(null); + const [error, setError] = useState(null); + const [minter, setMinter] = useState(definition.minter); + const [statsSource, setStatsSource] = useState(definition.statsSource); + const [newArtist, setNewArtist] = useState(''); + const [customProvider, setCustomProvider] = useState(''); + const [art, setArt] = useState>>({}); + + async function run(label: string, build: () => Parameters[0]) { + setBusy(label); + setError(null); + try { + await client.execute(build()); + onChanged(); + } catch (e) { + setError(e instanceof Error ? e.message : String(e)); + } finally { + setBusy(null); + } + } + + const paused = BigInt(definition.minter) === 0n; + const artComplete = ART_SLOTS.every(({ slot }) => art[slot]); + + return ( +
+
+
+

+ {definition.name} #{beastId.toString()} +

+

+ {BEAST_TYPE_NAMES[definition.beastType]} · Tier {definition.tier} ·{' '} + {definition.factoryProvider ? 'Verified art' : 'Custom provider'} +

+
+
+ {paused && Minting paused} + {definition.artLocked && Art locked} + {definition.minterLocked && Minter locked} +
+
+ + {!isArtist && ( +

+ You are not the artist for this species. These controls are read-only. +

+ )} + {error &&

{error}

} + +
+

Minting

+ {definition.minterLocked ? ( +

+ The minter is locked to {short(definition.minter)} and can + never change. Holders can rely on that. +

+ ) : ( + <> +

+ Set to zero to pause. Pausing stops new mints; it never affects + Beasts already minted. +

+
+ setMinter(e.target.value)} + /> + + +
+ + + )} +
+ +
+

Artwork

+ {definition.artLocked ? ( +

+ Art is locked.{' '} + {definition.factoryProvider + ? 'This species is frozen: the art is stored onchain and can never change.' + : 'The provider address is frozen, but a custom provider can still change what it returns — so refreshes stay available.'} +

+ ) : definition.factoryProvider ? ( + <> +

+ Replacing art re-renders every Beast of this species and notifies + marketplaces automatically. Limited to one refresh per hour. +

+
+ {ART_SLOTS.map(({ slot, label, kind, accept }) => ( + + ))} +
+ + + ) : ( + <> +

+ This species renders through your own provider at{' '} + {short(definition.artProvider)}. Announce changes so + marketplaces re-read it. +

+ + + )} + +
+ Advanced: swap art provider +

+ Point this species at your own IBeastArtProvider contract + to vary art by affix, tier or level. Your provider must return an + allowlisted image data URI or rendering will fail for your species. +

+
+ setCustomProvider(e.target.value)} + /> + +
+
+ + {!definition.artLocked && ( + + )} +
+ +
+

Kill stats

+

+ Optional. A stats source lets your Beasts show how many Adventurers + they have slain. It must implement the stats interface; set zero to + turn stats off. +

+
+ setStatsSource(e.target.value)} + /> + +
+
+ +
+

Transfer artist role

+

+ Hands every control on this page to another address. This does not move + your Genesis Beast — that is an ordinary NFT you keep or sell + separately. +

+
+ setNewArtist(e.target.value)} + /> + +
+
+
+ ); +} + +function short(address: string): string { + const hex = BigInt(address).toString(16); + if (hex === '0') return '0x0'; + return `0x${hex.slice(0, 4)}…${hex.slice(-4)}`; +} diff --git a/app/src/components/RegisterForm.tsx b/app/src/components/RegisterForm.tsx new file mode 100644 index 0000000..8393287 --- /dev/null +++ b/app/src/components/RegisterForm.tsx @@ -0,0 +1,243 @@ +import { useAccount } from '@starknet-react/core'; +import { + BEAST_TYPE_NAMES, + BeastType, + MAX_NAME_BYTES, + MAX_SUPPLY_PER_SPECIES, + validateSpeciesName, + validateTier, +} from '@provable-games/beasts-sdk'; +import { useMemo, useState } from 'react'; +import { ART_SLOTS, totalStorageSlots, type ArtSlot, type LoadedArt } from '../lib/art'; +import { ArtUpload } from './ArtUpload'; +import { CardPreview } from './CardPreview'; + +export interface RegistrationInput { + name: string; + tier: number; + beastType: BeastType; + minter: string; + art: { pngRegular: string; pngShiny: string; gifRegular: string; gifShiny: string }; +} + +interface Props { + onSubmit: (input: RegistrationInput) => void; + submitting: boolean; + error?: string; +} + +const ZERO = '0x0'; + +export function RegisterForm({ onSubmit, submitting, error }: Props) { + const { address } = useAccount(); + const [name, setName] = useState(''); + const [tier, setTier] = useState(3); + const [beastType, setBeastType] = useState(BeastType.Magic); + const [minterMode, setMinterMode] = useState<'later' | 'custom'>('later'); + const [minter, setMinter] = useState(''); + const [loaded, setLoaded] = useState>>({}); + const [preview, setPreview] = useState('pngRegular'); + + const nameCheck = name ? validateSpeciesName(name) : { valid: false }; + const tierCheck = validateTier(tier); + const missingArt = ART_SLOTS.filter(({ slot }) => !loaded[slot]); + const minterValid = minterMode === 'later' || /^0x[0-9a-fA-F]{1,64}$/.test(minter.trim()); + + const ready = + nameCheck.valid && tierCheck.valid && missingArt.length === 0 && minterValid && !!address; + + const slots = useMemo(() => totalStorageSlots(loaded), [loaded]); + + function submit() { + if (!ready) return; + onSubmit({ + name, + tier, + beastType, + minter: minterMode === 'later' ? ZERO : minter.trim(), + art: { + pngRegular: loaded.pngRegular!.dataUri, + pngShiny: loaded.pngShiny!.dataUri, + gifRegular: loaded.gifRegular!.dataUri, + gifShiny: loaded.gifShiny!.dataUri, + }, + }); + } + + return ( +
+
+
+

1. Artwork

+

+ All four variants are required. Which one a Beast shows is decided by + its token ID, so a species cannot ship a partial set. +

+ setLoaded((l) => ({ ...l, [slot]: art }))} + disabled={submitting} + /> + {slots > 0 && ( +

+ About {slots.toLocaleString()} storage slots. There is no size cap — + if you are willing to pay for it and the network accepts it, it is + valid — but larger art means a more expensive registration. +

+ )} +
+ +
+

2. Identity

+ + + + + + +
+ +
+

3. Who can mint it

+

+ Usually a Loot Survivor dungeon. Players earn your Beast by + defeating it there — Beasts are not sold, they are captured. +

+ + + + + + {minterMode === 'custom' && ( + + )} +
+ +
+

4. Register

+
    +
  • + Your wallet receives the Genesis Beast — the + creator's token, one per species, in the same transaction. +
  • +
  • + Your species is capped at {MAX_SUPPLY_PER_SPECIES.toLocaleString()}{' '} + Beasts forever. +
  • +
  • + Name, type and tier can never change. Art and + minter can, until you lock them. +
  • +
+ + {!address &&

Connect a wallet to register.

} + {missingArt.length > 0 && ( +

+ Still needed: {missingArt.map((s) => s.label).join(', ')} +

+ )} + {error &&

{error}

} + + +
+
+ + +
+ ); +} diff --git a/app/src/lib/art.ts b/app/src/lib/art.ts new file mode 100644 index 0000000..13a016e --- /dev/null +++ b/app/src/lib/art.ts @@ -0,0 +1,109 @@ +import { validateFactoryArt, type ValidationResult } from '@provable-games/beasts-sdk'; + +export type ArtSlot = 'pngRegular' | 'pngShiny' | 'gifRegular' | 'gifShiny'; + +export interface ArtSlotSpec { + slot: ArtSlot; + label: string; + hint: string; + kind: 'png' | 'gif'; + accept: string; +} + +/** + * The four variants a factory-provider species stores. Which one a token + * renders is decided by the shiny and animated bits in its token ID, so all + * four are required — a species cannot ship a partial set. + */ +export const ART_SLOTS: readonly ArtSlotSpec[] = [ + { + slot: 'pngRegular', + label: 'Standard', + hint: 'The default look. Shown when a Beast is neither shiny nor animated.', + kind: 'png', + accept: 'image/png', + }, + { + slot: 'pngShiny', + label: 'Shiny', + hint: 'The rare colourway. Static.', + kind: 'png', + accept: 'image/png', + }, + { + slot: 'gifRegular', + label: 'Animated', + hint: 'The default look, in motion.', + kind: 'gif', + accept: 'image/gif', + }, + { + slot: 'gifShiny', + label: 'Animated + Shiny', + hint: 'The rarest combination. Both bits set.', + kind: 'gif', + accept: 'image/gif', + }, +]; + +export interface LoadedArt { + dataUri: string; + bytes: number; + /** On-chain storage cost: art is stored 31 bytes per felt slot. */ + slots: number; +} + +export class ArtLoadError extends Error {} + +/** + * Reads a file into a base64 data URI and checks it against the same rules + * the factory provider enforces on write. + * + * The browser's own decode is the real format check — magic bytes only prove + * the header, and a file that cannot be decoded here would render as a broken + * image for every holder of the species. + */ +export async function loadArtFile(file: File, kind: 'png' | 'gif'): Promise { + const dataUri = await readAsDataUri(file); + + const validation: ValidationResult = validateFactoryArt(dataUri, kind); + if (!validation.valid) throw new ArtLoadError(validation.error ?? 'Invalid art'); + + await assertDecodable(dataUri); + + const bytes = dataUri.length; + return { dataUri, bytes, slots: Math.ceil(bytes / 31) }; +} + +function readAsDataUri(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onerror = () => reject(new ArtLoadError('Could not read that file')); + reader.onload = () => { + const result = reader.result; + if (typeof result !== 'string') { + reject(new ArtLoadError('Could not read that file')); + return; + } + resolve(result); + }; + reader.readAsDataURL(file); + }); +} + +function assertDecodable(dataUri: string): Promise { + return new Promise((resolve, reject) => { + const image = new Image(); + image.onload = () => resolve(); + image.onerror = () => reject(new ArtLoadError('That file is not a valid image')); + image.src = dataUri; + }); +} + +/** + * Rough cost signal for the registration transaction. Advisory only — the + * contract imposes no size cap, and the network decides what it will accept. + */ +export function totalStorageSlots(loaded: Partial>): number { + return ART_SLOTS.reduce((sum, { slot }) => sum + (loaded[slot]?.slots ?? 0), 0); +} diff --git a/app/src/lib/chain.ts b/app/src/lib/chain.ts new file mode 100644 index 0000000..1240468 --- /dev/null +++ b/app/src/lib/chain.ts @@ -0,0 +1,48 @@ +import ControllerConnector from '@cartridge/connector/controller'; +import { sepolia } from '@starknet-react/chains'; +import { SEPOLIA_ADDRESSES } from '@provable-games/beasts-sdk'; +import { RpcProvider } from 'starknet'; + +export const RPC_URL = + import.meta.env.VITE_STARKNET_RPC_URL ?? + 'https://api.cartridge.gg/x/starknet/sepolia'; + +export const ADDRESSES = { + nft: import.meta.env.VITE_BEASTS_NFT ?? SEPOLIA_ADDRESSES.nft, + registry: import.meta.env.VITE_BEASTS_REGISTRY ?? SEPOLIA_ADDRESSES.registry, +}; + +export const chains = [sepolia]; + +export const provider = () => new RpcProvider({ nodeUrl: RPC_URL }); + +/** + * Cartridge Controller with the registry entrypoints pre-approved, so an + * artist signs once and can then iterate on their species — update art, rotate + * the minter, refresh metadata — without a popup for every change. + * + * `register_beast_with_art` is deliberately NOT in the session policy: it + * mints the artist's provenance token and permanently assigns a species ID, so + * it should always be an explicit, visible signature. + */ +export const connectors = [ + new ControllerConnector({ + chains: [{ rpcUrl: RPC_URL }], + // Must be 0x-prefixed hex; the bare digits parse as neither hex nor decimal. + defaultChainId: `0x${sepolia.id.toString(16)}`, + policies: { + contracts: { + [ADDRESSES.registry]: { + name: 'Beast Registry', + methods: [ + { name: 'Update art', entrypoint: 'update_art' }, + { name: 'Set minter', entrypoint: 'set_minter' }, + { name: 'Set art provider', entrypoint: 'set_art_provider' }, + { name: 'Refresh metadata', entrypoint: 'notify_art_updated' }, + { name: 'Set stats source', entrypoint: 'set_stats_source' }, + ], + }, + }, + }, + }), +]; diff --git a/app/src/main.tsx b/app/src/main.tsx new file mode 100644 index 0000000..fdd5c03 --- /dev/null +++ b/app/src/main.tsx @@ -0,0 +1,25 @@ +import { StarknetConfig, jsonRpcProvider, voyager } from '@starknet-react/core'; +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { App } from './App'; +import { RPC_URL, chains, connectors } from './lib/chain'; +import './styles.css'; + +// `publicProvider()` pins RPC spec 0.8.1, which starknet 9.x no longer +// supports — it throws before the tree ever renders. Supplying the node URL +// directly lets the provider negotiate whatever the node actually speaks. +const rpc = () => ({ nodeUrl: RPC_URL }); + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + + + , +); diff --git a/app/src/styles.css b/app/src/styles.css new file mode 100644 index 0000000..62464e9 --- /dev/null +++ b/app/src/styles.css @@ -0,0 +1,552 @@ +:root { + --bg: #131316; + --panel: #1e1e22; + --panel-2: #2d2d32; + --line: #ffffff14; + --text: #ececf0; + --muted: #9a9aa4; + --gold: #b79a5e; + --gold-bright: #e5d8b2; + --danger: #d4674f; + --radius: 10px; + color-scheme: dark; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + background: var(--bg); + color: var(--text); + font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif; +} + +code { + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 0.9em; + color: var(--gold-bright); +} + +.app { + max-width: 1140px; + margin: 0 auto; + padding: 0 20px 64px; +} + +/* ------------------------------------------------------------- topbar */ + +.topbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 18px 0; + border-bottom: 1px solid var(--line); + flex-wrap: wrap; +} + +.brand { + background: none; + border: 0; + padding: 0; + color: var(--gold-bright); + font-size: 17px; + font-weight: 600; + letter-spacing: 0.01em; + cursor: pointer; +} + +.topbar__right { + display: flex; + align-items: center; + gap: 10px; +} + +.lookup { + display: flex; + gap: 6px; +} + +.lookup input { + width: 110px; +} + +/* ------------------------------------------------------------ controls */ + +button { + background: var(--panel-2); + color: var(--text); + border: 1px solid var(--line); + border-radius: var(--radius); + padding: 9px 14px; + font: inherit; + font-size: 14px; + cursor: pointer; + transition: background 0.15s, border-color 0.15s; +} + +button:hover:not(:disabled) { + border-color: #ffffff2e; + background: #35353c; +} + +button:disabled { + opacity: 0.45; + cursor: not-allowed; +} + +button.primary { + background: linear-gradient(135deg, var(--gold-bright), var(--gold)); + color: #23201a; + border-color: transparent; + font-weight: 600; +} + +button.danger { + border-color: #d4674f4d; + color: var(--danger); + background: transparent; + margin-top: 12px; +} + +button.danger:hover:not(:disabled) { + background: #d4674f1a; +} + +input, +select { + background: #16161a; + color: var(--text); + border: 1px solid var(--line); + border-radius: var(--radius); + padding: 9px 11px; + font: inherit; + font-size: 14px; + width: 100%; +} + +input:focus, +select:focus { + outline: none; + border-color: var(--gold); +} + +/* --------------------------------------------------------------- hero */ + +.hero { + padding: 44px 0 28px; + max-width: 640px; +} + +.hero h1 { + margin: 0 0 12px; + font-size: 34px; + line-height: 1.15; + letter-spacing: -0.02em; +} + +.hero p { + margin: 0 0 8px; + color: #c9c9d2; +} + +.muted { + color: var(--muted); + font-size: 14px; +} + +/* ----------------------------------------------------------- register */ + +.register { + display: grid; + grid-template-columns: minmax(0, 1fr) 300px; + gap: 36px; + align-items: start; +} + +@media (max-width: 900px) { + .register { + grid-template-columns: 1fr; + } +} + +.register__form section { + padding: 22px 0; + border-top: 1px solid var(--line); +} + +.register__form h2 { + margin: 0 0 6px; + font-size: 16px; + letter-spacing: 0.01em; +} + +.register__preview { + position: sticky; + top: 20px; +} + +.field { + display: block; + margin: 14px 0; +} + +.field > span { + display: block; + margin-bottom: 6px; + font-size: 13px; + color: var(--muted); +} + +.field__hint, +.field__error { + display: block; + margin-top: 6px; + font-size: 12.5px; + font-style: normal; +} + +.field__hint { + color: var(--muted); +} + +.field__error { + color: var(--danger); +} + +.radio { + display: flex; + gap: 10px; + align-items: flex-start; + padding: 11px 0; + cursor: pointer; +} + +.radio input { + width: auto; + margin-top: 3px; +} + +.radio span { + display: block; +} + +.radio em { + display: block; + color: var(--muted); + font-size: 13px; + font-style: normal; + margin-top: 2px; +} + +.summary { + margin: 0 0 18px; + padding-left: 18px; + color: #c9c9d2; + font-size: 14px; +} + +.summary li { + margin: 6px 0; +} + +/* ------------------------------------------------------------ art grid */ + +.art-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); + gap: 12px; + margin: 16px 0; +} + +.art-slot { + background: var(--panel); + border: 1px solid var(--line); + border-radius: var(--radius); + padding: 12px; +} + +.art-slot--selected { + border-color: var(--gold); +} + +.art-slot--error { + border-color: var(--danger); +} + +.art-slot__header { + display: flex; + justify-content: space-between; + align-items: baseline; + margin-bottom: 8px; +} + +.art-slot__label { + font-size: 13px; + font-weight: 600; +} + +.art-slot__kind { + font-size: 11px; + color: var(--muted); +} + +.art-slot__drop { + display: block; + position: relative; + aspect-ratio: 1; + background: #000; + border-radius: 6px; + overflow: hidden; + cursor: pointer; + display: grid; + place-items: center; +} + +.art-slot__drop input, +.art-slot--compact input { + position: absolute; + inset: 0; + opacity: 0; + cursor: pointer; + width: 100%; +} + +.art-slot img { + width: 100%; + height: 100%; + object-fit: contain; + image-rendering: pixelated; +} + +.art-slot__placeholder { + color: var(--muted); + font-size: 12px; +} + +.art-slot__hint { + margin: 8px 0 0; + font-size: 12px; + color: var(--muted); +} + +.art-slot__meta { + margin: 4px 0 0; + font-size: 11.5px; + color: var(--gold); +} + +.art-slot__error { + margin: 6px 0 0; + font-size: 12px; + color: var(--danger); +} + +.art-grid--compact { + grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); +} + +.art-slot--compact { + position: relative; + display: grid; + gap: 6px; + place-items: center; + cursor: pointer; +} + +.art-slot--compact img { + aspect-ratio: 1; +} + +/* ---------------------------------------------------------------- card */ + +.card { + background: linear-gradient(180deg, var(--panel-2), var(--panel)); + border: 2px solid transparent; + border-radius: 14px; + padding: 14px; + background-clip: padding-box; + box-shadow: 0 0 0 2px #ffffff10; +} + +.card--shiny { + box-shadow: 0 0 0 2px var(--gold), 0 0 22px #b79a5e40; +} + +.card__title { + font-size: 14px; + font-weight: 600; + color: var(--gold-bright); + text-align: center; + margin-bottom: 10px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.card__art { + aspect-ratio: 220 / 144; + background: #000; + border-radius: 8px; + display: grid; + place-items: center; + overflow: hidden; +} + +.card__art img { + width: 100%; + height: 100%; + object-fit: contain; + image-rendering: pixelated; +} + +.card__art-empty { + color: var(--muted); + font-size: 12px; +} + +.card__stats { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 8px; + margin-top: 10px; +} + +.stat { + background: var(--panel); + border-radius: 6px; + padding: 7px 8px; + text-align: center; +} + +.stat__label { + font-size: 10px; + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.06em; +} + +.stat__value { + font-size: 15px; + font-weight: 600; + color: var(--gold-bright); +} + +.card__note { + margin: 12px 0 0; + font-size: 11.5px; + color: var(--muted); + text-align: center; +} + +/* ----------------------------------------------------------- dashboard */ + +.dashboard { + padding-top: 32px; +} + +.dashboard__header { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 16px; + flex-wrap: wrap; + padding-bottom: 18px; + border-bottom: 1px solid var(--line); +} + +.dashboard__header h2 { + margin: 0; + font-size: 24px; +} + +.dashboard__header p { + margin: 4px 0 0; +} + +.badges { + display: flex; + gap: 8px; + flex-wrap: wrap; +} + +.badge { + border: 1px solid var(--line); + border-radius: 999px; + padding: 4px 11px; + font-size: 12px; + color: var(--muted); +} + +.badge--warn { + border-color: #d4674f4d; + color: var(--danger); +} + +.panel { + padding: 22px 0; + border-bottom: 1px solid var(--line); +} + +.panel h3 { + margin: 0 0 6px; + font-size: 15px; +} + +.panel p { + margin: 0 0 12px; +} + +.row { + display: flex; + gap: 8px; + margin: 12px 0; + flex-wrap: wrap; +} + +.row input { + flex: 1 1 240px; +} + +.row button { + white-space: nowrap; +} + +.advanced { + margin-top: 16px; + border-top: 1px solid var(--line); + padding-top: 14px; +} + +.advanced summary { + cursor: pointer; + font-size: 14px; + color: var(--muted); +} + +.notice { + background: #b79a5e1a; + border: 1px solid #b79a5e33; + border-radius: var(--radius); + padding: 11px 14px; + font-size: 14px; + margin: 18px 0; +} + +.empty { + padding: 80px 0; + text-align: center; + display: grid; + gap: 14px; + place-items: center; +} + +.footer { + margin-top: 48px; + padding-top: 18px; + border-top: 1px solid var(--line); + font-size: 12.5px; + color: var(--muted); +} diff --git a/app/src/vite-env.d.ts b/app/src/vite-env.d.ts new file mode 100644 index 0000000..8e73e6d --- /dev/null +++ b/app/src/vite-env.d.ts @@ -0,0 +1,11 @@ +/// + +interface ImportMetaEnv { + readonly VITE_STARKNET_RPC_URL?: string; + readonly VITE_BEASTS_NFT?: string; + readonly VITE_BEASTS_REGISTRY?: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/app/tsconfig.json b/app/tsconfig.json new file mode 100644 index 0000000..c9d766b --- /dev/null +++ b/app/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "isolatedModules": true + }, + "include": ["src"] +} diff --git a/app/vite.config.ts b/app/vite.config.ts new file mode 100644 index 0000000..fabde1a --- /dev/null +++ b/app/vite.config.ts @@ -0,0 +1,6 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [react()], +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..b8aedb0 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "beasts-monorepo", + "private": true, + "scripts": { + "test:sdk": "pnpm --filter @provable-games/beasts-sdk test", + "build:sdk": "pnpm --filter @provable-games/beasts-sdk build", + "dev:app": "pnpm --filter @provable-games/beasts-app dev", + "build:app": "pnpm --filter @provable-games/beasts-app build", + "typecheck": "pnpm -r typecheck", + "gen:tables": "node scripts/gen-tables.mjs" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..29e6fa3 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,5924 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: {} + + app: + dependencies: + '@cartridge/connector': + specifier: ^0.13.12 + version: 0.13.16(@starknet-react/core@5.0.3(get-starknet-core@4.0.0)(react@18.3.1)(starknet@9.4.2(typescript@5.9.3)(zod@3.25.76))(typescript@5.9.3))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@cartridge/controller': + specifier: ^0.13.12 + version: 0.13.16(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@provable-games/beasts-sdk': + specifier: workspace:* + version: link:../sdk + '@starknet-react/chains': + specifier: 5.0.3 + version: 5.0.3 + '@starknet-react/core': + specifier: ^5.0.1 + version: 5.0.3(get-starknet-core@4.0.0)(react@18.3.1)(starknet@9.4.2(typescript@5.9.3)(zod@3.25.76))(typescript@5.9.3) + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + starknet: + specifier: 9.4.2 + version: 9.4.2(typescript@5.9.3)(zod@3.25.76) + devDependencies: + '@types/react': + specifier: ^18.2.0 + version: 18.3.31 + '@types/react-dom': + specifier: ^18.2.0 + version: 18.3.7(@types/react@18.3.31) + '@vitejs/plugin-react': + specifier: ^4.3.0 + version: 4.7.0(vite@5.4.21(@types/node@22.7.5)) + playwright: + specifier: ^1.62.1 + version: 1.62.1 + typescript: + specifier: ^5.8.3 + version: 5.9.3 + vite: + specifier: ^5.4.0 + version: 5.4.21(@types/node@22.7.5) + + sdk: + devDependencies: + starknet: + specifier: 9.4.2 + version: 9.4.2(typescript@5.9.3)(zod@3.25.76) + typescript: + specifier: ^5.8.3 + version: 5.9.3 + vitest: + specifier: ^3.0.0 + version: 3.2.7(@types/node@22.7.5) + +packages: + + '@adraffy/ens-normalize@1.11.1': + resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==} + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-transform-react-jsx-self@7.29.7': + resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.29.7': + resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + + '@base-org/account@2.4.0': + resolution: {integrity: sha512-A4Umpi8B9/pqR78D1Yoze4xHyQaujioVRqqO3d6xuDFw9VRtjg6tK3bPlwE0aW+nVH/ntllCpPa2PbI8Rnjcug==} + + '@cartridge/connector@0.13.16': + resolution: {integrity: sha512-pXFRrWIqhb7GwNa4FJUr46Ke/v+68AyMKbeEwyoPgejtJQ2+WXSdJVE9E7AZ5v8EThLfCfHbQm7Ls0C9zZbe2g==} + peerDependencies: + '@starknet-react/core': ^5.0.1 + + '@cartridge/controller-wasm@0.10.1': + resolution: {integrity: sha512-NweHJ98lFrV103sT+ud0WOUT+j92bBdaTdT+cFRwPA+XmRB39UekMu35iWlFcBhlnxQF+GdX4G/IrQtfoXf9+A==} + + '@cartridge/controller@0.13.16': + resolution: {integrity: sha512-fb43enXNabH8jj2pIqBVNuzZE9NBEXuecbw9VfJxK1ARwF/fM0ZDdCFGHe7n4eD+vA4/P8W9v4tPE1alUIZaIw==} + peerDependencies: + react: ^18.2.0 || ^19.0.0 + react-dom: ^18.2.0 || ^19.0.0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + + '@cartridge/penpal@6.2.4': + resolution: {integrity: sha512-tdpOnSJJBFMlgLZ1+z9Ho5e6cG5EgMAb1Cmmh1lGT2tmplogU/XPMjLE6CwvKAPDoe6a38iMnbH+ySTAWWIOKA==} + + '@cbor-extract/cbor-extract-darwin-arm64@2.2.2': + resolution: {integrity: sha512-ZKZ/F8US7JR92J4DMct6cLW/Y66o2K576+zjlEN/MevH70bFIsB10wkZEQPLzl2oNh2SMGy55xpJ9JoBRl5DOA==} + cpu: [arm64] + os: [darwin] + + '@cbor-extract/cbor-extract-darwin-x64@2.2.2': + resolution: {integrity: sha512-32b1mgc+P61Js+KW9VZv/c+xRw5EfmOcPx990JbCBSkYJFY0l25VinvyyWfl+3KjibQmAcYwmyzKF9J4DyKP/Q==} + cpu: [x64] + os: [darwin] + + '@cbor-extract/cbor-extract-linux-arm64@2.2.2': + resolution: {integrity: sha512-wfqgzqCAy/Vn8i6WVIh7qZd0DdBFaWBjPdB6ma+Wihcjv0gHqD/mw3ouVv7kbbUNrab6dKEx/w3xQZEdeXIlzg==} + cpu: [arm64] + os: [linux] + + '@cbor-extract/cbor-extract-linux-arm@2.2.2': + resolution: {integrity: sha512-tNg0za41TpQfkhWjptD+0gSD2fggMiDCSacuIeELyb2xZhr7PrhPe5h66Jc67B/5dmpIhI2QOUtv4SBsricyYQ==} + cpu: [arm] + os: [linux] + + '@cbor-extract/cbor-extract-linux-x64@2.2.2': + resolution: {integrity: sha512-rpiLnVEsqtPJ+mXTdx1rfz4RtUGYIUg2rUAZgd1KjiC1SehYUSkJN7Yh+aVfSjvCGtVP0/bfkQkXpPXKbmSUaA==} + cpu: [x64] + os: [linux] + + '@cbor-extract/cbor-extract-win32-x64@2.2.2': + resolution: {integrity: sha512-dI+9P7cfWxkTQ+oE+7Aa6onEn92PHgfWXZivjNheCRmTBDBf2fx6RyTi0cmgpYLnD1KLZK9ZYrMxaPZ4oiXhGA==} + cpu: [x64] + os: [win32] + + '@coinbase/cdp-sdk@1.54.0': + resolution: {integrity: sha512-FfIJVEKAXgmr+dkXn/NBQO04/pps+oIgqEIdcmG67WZh+m07OsVnvSBEqEvbFO+VjSdaQAKu69EpO3NdHJd2Iw==} + peerDependencies: + '@x402/core': ^2.19.0 + '@x402/evm': ^2.19.0 + '@x402/extensions': ^2.19.0 + '@x402/svm': ^2.19.0 + peerDependenciesMeta: + '@x402/core': + optional: true + '@x402/evm': + optional: true + '@x402/extensions': + optional: true + '@x402/svm': + optional: true + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@hpke/chacha20poly1305@1.8.0': + resolution: {integrity: sha512-FcBfAQ+Y99vMNJP2yrZ9wpL8V0GOwp1+zMyzvc6alasrBygfFjFm1yeUtyADJCu/27C3Lm5mJzx6u7pwg+cX5w==} + engines: {node: '>=16.0.0'} + + '@hpke/common@1.10.1': + resolution: {integrity: sha512-moJwhmtLtuxiUzzNp1jpfBfx8yefKoO9D/RCR9dmwrnc7qjJqId1rEtQz+lSlU5cabX8daToMSx/7HayXOiaFw==} + engines: {node: '>=16.0.0'} + + '@hpke/core@1.9.0': + resolution: {integrity: sha512-pFxWl1nNJeQCSUFs7+GAblHvXBCjn9EPN65vdKlYQil2aURaRxfGMO6vBKGqm1YHTKwiAxJQNEI70PbSowMP9Q==} + engines: {node: '>=16.0.0'} + + '@hpke/dhkem-x25519@1.8.0': + resolution: {integrity: sha512-S1MWWkAfu+TFxySgv5+2P3O4Mx/jk7BsoplzQaA1s3sfUJVJ2UsZsSzSsMc+FXJumLXncoJFlO6mK6mDGspfmA==} + engines: {node: '>=16.0.0'} + + '@hpke/dhkem-x448@1.8.0': + resolution: {integrity: sha512-mFfnZfgp4OKkUIS/FKikfUgdnDKRy25ytCKBQiV+N+HbYy3I4v4ZCPBQ69QL+TYmKmCZJeUEnYeS5K+OBRP+Eg==} + engines: {node: '>=16.0.0'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@lit-labs/ssr-dom-shim@1.6.0': + resolution: {integrity: sha512-VHb0ALPMTlgKjM6yIxxoQNnpKyUKLD04VzeQdsiXkMqkvYlAHxq9glGLmgbb889/1GsohSOAjvQYoiBppXFqrQ==} + + '@lit/react@1.0.8': + resolution: {integrity: sha512-p2+YcF+JE67SRX3mMlJ1TKCSTsgyOVdAwd/nxp3NuV1+Cb6MWALbN6nT7Ld4tpmYofcE5kcaSY1YBB9erY+6fw==} + peerDependencies: + '@types/react': 17 || 18 || 19 + + '@lit/reactive-element@2.1.2': + resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} + + '@module-federation/error-codes@0.12.0': + resolution: {integrity: sha512-DEXQjopcBuGzp/NA9OVtASO0uZ6grVK5TIe0PjrbDRyZDxVaYQXKrISxBLOE+3nSIELE98tYpfxptm8WC9A8zA==} + + '@module-federation/runtime-core@0.12.0': + resolution: {integrity: sha512-373zBM54196KHURs/O8lry9trCAM3PPidvsF4YdrtahNc8YaQynml0mE3zdZeBnqP6H0/4OpPqMMjACI80Ht8w==} + + '@module-federation/runtime@0.12.0': + resolution: {integrity: sha512-Cz9/7+gSvrdencwA8LXUMKnZdu0/flyN+yk6t3pkxfhvPJi3W65ZcalAKyOgyk2x8rEYrRSyEXu+/2DIFgrzmA==} + + '@module-federation/sdk@0.12.0': + resolution: {integrity: sha512-vh3GcG90fxjbkMghK7iSWcMayi/y8U5DxI6mhEFuz11St3y1UgQO2TZYephL8nISFBld7DdiqAkimx+6Hb3hjQ==} + + '@msgpack/msgpack@3.1.3': + resolution: {integrity: sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==} + engines: {node: '>= 18'} + + '@noble/ciphers@1.3.0': + resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.2.0': + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + + '@noble/curves@1.7.0': + resolution: {integrity: sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.8.0': + resolution: {integrity: sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.9.0': + resolution: {integrity: sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.9.1': + resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.9.7': + resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.3.2': + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + + '@noble/hashes@1.4.0': + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + + '@noble/hashes@1.6.0': + resolution: {integrity: sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.6.1': + resolution: {integrity: sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.7.0': + resolution: {integrity: sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@peculiar/asn1-cms@2.8.0': + resolution: {integrity: sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA==} + + '@peculiar/asn1-csr@2.8.0': + resolution: {integrity: sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg==} + + '@peculiar/asn1-ecc@2.8.0': + resolution: {integrity: sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ==} + + '@peculiar/asn1-pfx@2.8.0': + resolution: {integrity: sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg==} + + '@peculiar/asn1-pkcs8@2.8.0': + resolution: {integrity: sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA==} + + '@peculiar/asn1-pkcs9@2.8.0': + resolution: {integrity: sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ==} + + '@peculiar/asn1-rsa@2.8.0': + resolution: {integrity: sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg==} + + '@peculiar/asn1-schema@2.8.0': + resolution: {integrity: sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==} + + '@peculiar/asn1-x509-attr@2.8.0': + resolution: {integrity: sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA==} + + '@peculiar/asn1-x509@2.8.0': + resolution: {integrity: sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg==} + + '@peculiar/utils@2.0.3': + resolution: {integrity: sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==} + + '@peculiar/x509@1.12.3': + resolution: {integrity: sha512-+Mzq+W7cNEKfkNZzyLl6A6ffqc3r21HGZUezgfKxpZrkORfOqgRXnS80Zu0IV6a9Ue9QBJeKD7kN0iWfc3bhRQ==} + + '@phosphor-icons/webcomponents@2.1.5': + resolution: {integrity: sha512-JcvQkZxvcX2jK+QCclm8+e8HXqtdFW9xV4/kk2aL9Y3dJA2oQVt+pzbv1orkumz3rfx4K9mn9fDoMr1He1yr7Q==} + + '@reown/appkit-common@1.8.19': + resolution: {integrity: sha512-z5wDrYjUGY7YbM4b14NHVo54WKZ5++PQtGkcsXhiOP39yAVijubBQD8BfHs/Pu2fSFqnqLIFoCVvIEfNWWccRw==} + + '@reown/appkit-controllers@1.8.19': + resolution: {integrity: sha512-JFNT8CfAVit9FJXh596Ye4U8A/oIapW+Y0KQqjB59DXyTCDZbxZDB32rULBQrSkZ6PufTEa239Dil4kABCQKtg==} + + '@reown/appkit-pay@1.8.19': + resolution: {integrity: sha512-HO/tQT0TbTQO3eONxNNPJAOZAOzUiHvjM0Mty1rFFeRBH68auiqQxQi2YFNMs014gNkRN+cb84VYau7+MCC0fQ==} + + '@reown/appkit-polyfills@1.8.19': + resolution: {integrity: sha512-PSoetRSuZg7f2YFPzdfs4BayQl51zcGqYr7frwOe6td0XEsspLrrVFn/zk5QFbFHZVsMdfRZ+TTunt84ozRdnQ==} + + '@reown/appkit-scaffold-ui@1.8.19': + resolution: {integrity: sha512-Ak767x0VzeDIXb0wbzkl19kx6udw7vkb1EU0SAweG3iKc9BunW87Rfcd48/YimzMZycJaYmlbtfmqQQDYs6Few==} + + '@reown/appkit-ui@1.8.19': + resolution: {integrity: sha512-fCAwW8yyyC3JcgKLBPvCtYuDGC4H8anO7u4LTaAXGEzdcU5H+IrCgNFSPNK7NuTSmgXm1TnoYxPxRFKNiNwFdA==} + + '@reown/appkit-utils@1.8.19': + resolution: {integrity: sha512-VQPgUMTFqoh4UD3EDZSw9wyMkyZsmIVmu8CdQ2FUxIuqYW4fLd0VIpkDeO64MMhSv8b0X8Vd6m4+eGcqSwlUAg==} + peerDependencies: + valtio: 2.1.7 + + '@reown/appkit-wallet@1.8.19': + resolution: {integrity: sha512-NVdIKceUhkXYtsG32925ctmVn0QJFNyDlr+mWheMLCEZ/IUPn+6aA53vTVaSUquhyeFxUXtrCOh3ln6v1tup5w==} + + '@reown/appkit@1.8.19': + resolution: {integrity: sha512-wB+xatkRbOy0AY1cZxxtcKzzPk3l3CTFulDbaISLVmZI6ZnQrOFuLnYc285zGsC6DB4d6bmwYUh89zcMLa4PvQ==} + + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + + '@rollup/rollup-android-arm-eabi@4.62.3': + resolution: {integrity: sha512-c0wdcekXtQvvn5Tsrk/+op/gUArrbWaFduBnTLP2l1cKLSQs4diMWjJw3m6A0DdzT8dAAX95KpkJ3qynCePbmw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.62.3': + resolution: {integrity: sha512-3YjElDdWN+qXAFbJ/CzPV+0wspLqh54k/I6GfdYtEJRqg7buSgc1yPM3B+93j1M4neobtkATHZTmxK2AMVGfnA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.62.3': + resolution: {integrity: sha512-Pch2pFNOxxz1hTjypIdPyRTR6riiwRl84+VcN9djS680fw+Co1nAJINrdpqp7KV0NvyuU8ilZXZCjd7ykJl1GQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.62.3': + resolution: {integrity: sha512-LEuncFUHFiF8t4yZVZvvZA1wk0pjAscRnsrn1EfTEmN4HXotBi2YtcnLRyaK6UbuczW7xZS5ES+81Rdz8Z0T6g==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.62.3': + resolution: {integrity: sha512-zvBUvsQUpOWALdDsk6qbS8bXf2VxmPisuudNDrY7x0p0jBdsoZl8HsHczIOgkQiZldmcacMKtBzpoGVNeIe2bQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.62.3': + resolution: {integrity: sha512-C2KmNrcSem/AMg984H/dev+si0lieQGdXdR/lYGJnuumXnFb9Y7QdiI62obFdLlxRYLBv4P0eUVIDbD4c1vVvw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.62.3': + resolution: {integrity: sha512-ggXnsTAEzNQx74XpunRsiZ9aBZDsI7XIa0hm2nzR9f4WzH5/f/d73ZSDaC5ejJ8YLY4NW+V3wr0tjOaeCq8hqA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.62.3': + resolution: {integrity: sha512-2vng+FlzNUhKZxtej3IUqJgbZoQk2M/dwQM20+ULV0R/E/8tr9/P6uEf2iiGIk4HL0zMKh5Jry7mUHdUOvyGgA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.62.3': + resolution: {integrity: sha512-LLLFZKt4/Nraf9rxDkhiU8QVgLF4WmCkfr0L4fj0fPfIZFBib0DeiFk1hhaYKd03LFAFJcxHslhDFlNJLylf5Q==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.62.3': + resolution: {integrity: sha512-WJkdQCvS9sWNOUBJZfQRKpZGFBztRzcowI+nndmflKgU4XY+3a420FgTOSKTsVqJbnzSxeT4vaJalpOaPo2YCQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.62.3': + resolution: {integrity: sha512-PwHXCCS2n64/1Ot6rP1YEYA02MGYBcQlr8CSZZyrUG2O7NH6NklYmvr9v3Jy+5e/eDeNchc/ukmKJi9LuflMIQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.62.3': + resolution: {integrity: sha512-vUjxINQu3RC8NZS3ykk1gN65gIz8pAopOq2HXuZhiIxHdx7TFvDG+jgrdSgInu1Eza4/Rfi2VzZgyIgEH4WOaw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.62.3': + resolution: {integrity: sha512-wzko4aJ13+0G3kGnviCg5gnXFKd40izKsrf2uOw12US4XqprkDrmwOpeW14aSNa37V8bfPcz5Fkob6LZ3BAPmA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.62.3': + resolution: {integrity: sha512-8120ue0JUMSwy11stlwnfdX3pPd+WZYGCDBwEHWtIHi6pOpZmsEF5QKB7a/UN+XFdqvobxz98kv8RTqikyCEBw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.62.3': + resolution: {integrity: sha512-XLFHnR3tXMjbOCh2vtVJHmxt+995uJsTERQyseFDRA0xxMxyTZPLa3OIUlyFaO4mF/Lu0FjmWHCuPXJT1n/IOg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.62.3': + resolution: {integrity: sha512-se6yXvNGMIl0f+RQzyh7XAmia8/9kplQx424wnG2w0C1oi6XgO6Y8otKhdXFHbHs88Ihavzmvh1NWjuovE76BQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.62.3': + resolution: {integrity: sha512-gNoxRefktVIiGflpONuxWWXZAzIQG++z9qHO3xKwk4WdDMuQja3JHGfE1u0i3PfPDyvhypdk+WrgIJqLhGG7sg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.62.3': + resolution: {integrity: sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.62.3': + resolution: {integrity: sha512-LBx9LYXvj2CBkMkjLdNAWLwH0MLMin7do2VcVo9kVPibGLkY0BQQut2fv7NVqkXqZ/CrAu9LqDHVV1xHCMpCPw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.62.3': + resolution: {integrity: sha512-ABVf3Q0RCu7NcyCCOZQI0pJ3GuSdfSl8EXcy88QtdceIMIoCUdfhsJChZ64L9zVM2aJHjde1Bhn5uqSRcX9ySA==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.62.3': + resolution: {integrity: sha512-+2Cy/ldweGBLlPIKsQLF8U5N44a0KDdbrk1rAjHOM9M2K+kGdIVjHLmmrZIcx+9Ny3ke/1JomCsDI1ocb11+sg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.62.3': + resolution: {integrity: sha512-dtZvzc8BedpSaFNy75x6uiWwAGTH+aZHDtdrqP6qk+WcLJrfti6sGje1ZJ9UxyzDLF23d/mV+PaMwuC0hL7UVA==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.3': + resolution: {integrity: sha512-Rj8Ra4noo+aYy7sKBggCx0407mws34kAb1ySyWuq5DAtFBQdkSwnsjCgPrhPe9cvgBKZIukpE+CVHvORCS93kQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.3': + resolution: {integrity: sha512-vp7N084ew/odXn2gi/mzm9mUkQu9l6AiN6dt4IeUM2Uvm9o+cVmP+YkqbMOteLbiGgqBBlJZjIMYVCfOOIVbVQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.3': + resolution: {integrity: sha512-MOG/3gTOn4Fwf574RVOaY61I5o6P90legkFADiTyn1hyjNydT+cerU2rLUwPdZkKKyJ+iT+K9p7WXK4LM1Ka6g==} + cpu: [x64] + os: [win32] + + '@safe-global/safe-apps-provider@0.18.6': + resolution: {integrity: sha512-4LhMmjPWlIO8TTDC2AwLk44XKXaK6hfBTWyljDm0HQ6TWlOEijVWNrt2s3OCVMSxlXAcEzYfqyu1daHZooTC2Q==} + + '@safe-global/safe-apps-sdk@9.1.0': + resolution: {integrity: sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q==} + + '@safe-global/safe-gateway-typescript-sdk@3.23.1': + resolution: {integrity: sha512-6ORQfwtEJYpalCeVO21L4XXGSdbEMfyp2hEv6cP82afKXSwvse6d3sdelgaPWUxHIsFRkWvHDdzh8IyyKHZKxw==} + engines: {node: '>=16'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + '@scure/base@1.2.6': + resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} + + '@scure/bip32@1.7.0': + resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==} + + '@scure/bip39@1.6.0': + resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==} + + '@scure/starknet@1.1.0': + resolution: {integrity: sha512-83g3M6Ix2qRsPN4wqLDqiRZ2GBNbjVWfboJE/9UjfG+MHr6oDSu/CWgy8hsBSJejr09DkkL+l0Ze4KVrlCIdtQ==} + + '@solana-program/system@0.10.0': + resolution: {integrity: sha512-Go+LOEZmqmNlfr+Gjy5ZWAdY5HbYzk2RBewD9QinEU/bBSzpFfzqDRT55JjFRBGJUvMgf3C2vfXEGT4i8DSI4g==} + peerDependencies: + '@solana/kit': ^5.0 + + '@solana-program/token@0.9.0': + resolution: {integrity: sha512-vnZxndd4ED4Fc56sw93cWZ2djEeeOFxtaPS8SPf5+a+JZjKA/EnKqzbE1y04FuMhIVrLERQ8uR8H2h72eZzlsA==} + peerDependencies: + '@solana/kit': ^5.0 + + '@solana/accounts@5.5.1': + resolution: {integrity: sha512-TfOY9xixg5rizABuLVuZ9XI2x2tmWUC/OoN556xwfDlhBHBjKfszicYYOyD6nbFmwTGYarCmyGIdteXxTXIdhQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/addresses@5.5.1': + resolution: {integrity: sha512-5xoah3Q9G30HQghu/9BiHLb5pzlPKRC3zydQDmE3O9H//WfayxTFppsUDCL6FjYUHqj/wzK6CWHySglc2RkpdA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/assertions@5.5.1': + resolution: {integrity: sha512-YTCSWAlGwSlVPnWtWLm3ukz81wH4j2YaCveK+TjpvUU88hTy6fmUqxi0+hvAMAe4zKXpJyj3Az7BrLJRxbIm4Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/codecs-core@5.5.1': + resolution: {integrity: sha512-TgBt//bbKBct0t6/MpA8ElaOA3sa8eYVvR7LGslCZ84WiAwwjCY0lW/lOYsFHJQzwREMdUyuEyy5YWBKtdh8Rw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/codecs-data-structures@5.5.1': + resolution: {integrity: sha512-97bJWGyUY9WvBz3mX1UV3YPWGDTez6btCfD0ip3UVEXJbItVuUiOkzcO5iFDUtQT5riKT6xC+Mzl+0nO76gd0w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/codecs-numbers@5.5.1': + resolution: {integrity: sha512-rllMIZAHqmtvC0HO/dc/21wDuWaD0B8Ryv8o+YtsICQBuiL/0U4AGwH7Pi5GNFySYk0/crSuwfIqQFtmxNSPFw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/codecs-strings@5.5.1': + resolution: {integrity: sha512-7klX4AhfHYA+uKKC/nxRGP2MntbYQCR3N6+v7bk1W/rSxYuhNmt+FN8aoThSZtWIKwN6BEyR1167ka8Co1+E7A==} + engines: {node: '>=20.18.0'} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: ^5.0.0 + peerDependenciesMeta: + fastestsmallesttextencoderdecoder: + optional: true + typescript: + optional: true + + '@solana/codecs@5.5.1': + resolution: {integrity: sha512-Vea29nJub/bXjfzEV7ZZQ/PWr1pYLZo3z0qW0LQL37uKKVzVFRQlwetd7INk3YtTD3xm9WUYr7bCvYUk3uKy2g==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/errors@5.5.1': + resolution: {integrity: sha512-vFO3p+S7HoyyrcAectnXbdsMfwUzY2zYFUc2DEe5BwpiE9J1IAxPBGjOWO6hL1bbYdBrlmjNx8DXCslqS+Kcmg==} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/fast-stable-stringify@5.5.1': + resolution: {integrity: sha512-Ni7s2FN33zTzhTFgRjEbOVFO+UAmK8qi3Iu0/GRFYK4jN696OjKHnboSQH/EacQ+yGqS54bfxf409wU5dsLLCw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/functional@5.5.1': + resolution: {integrity: sha512-tTHoJcEQq3gQx5qsdsDJ0LEJeFzwNpXD80xApW9o/PPoCNimI3SALkZl+zNW8VnxRrV3l3yYvfHWBKe/X3WG3w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/instruction-plans@5.5.1': + resolution: {integrity: sha512-7z3CB7YMcFKuVvgcnNY8bY6IsZ8LG61Iytbz7HpNVGX2u1RthOs1tRW8luTzSG1MPL0Ox7afyAVMYeFqSPHnaQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/instructions@5.5.1': + resolution: {integrity: sha512-h0G1CG6S+gUUSt0eo6rOtsaXRBwCq1+Js2a+Ps9Bzk9q7YHNFA75/X0NWugWLgC92waRp66hrjMTiYYnLBoWOQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/keys@5.5.1': + resolution: {integrity: sha512-KRD61cL7CRL+b4r/eB9dEoVxIf/2EJ1Pm1DmRYhtSUAJD2dJ5Xw8QFuehobOGm9URqQ7gaQl+Fkc1qvDlsWqKg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/kit@5.5.1': + resolution: {integrity: sha512-irKUGiV2yRoyf+4eGQ/ZeCRxa43yjFEL1DUI5B0DkcfZw3cr0VJtVJnrG8OtVF01vT0OUfYOcUn6zJW5TROHvQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/nominal-types@5.5.1': + resolution: {integrity: sha512-I1ImR+kfrLFxN5z22UDiTWLdRZeKtU0J/pkWkO8qm/8WxveiwdIv4hooi8pb6JnlR4mSrWhq0pCIOxDYrL9GIQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/offchain-messages@5.5.1': + resolution: {integrity: sha512-g+xHH95prTU+KujtbOzj8wn+C7ZNoiLhf3hj6nYq3MTyxOXtBEysguc97jJveUZG0K97aIKG6xVUlMutg5yxhw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/options@5.5.1': + resolution: {integrity: sha512-eo971c9iLNLmk+yOFyo7yKIJzJ/zou6uKpy6mBuyb/thKtS/haiKIc3VLhyTXty3OH2PW8yOlORJnv4DexJB8A==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/plugin-core@5.5.1': + resolution: {integrity: sha512-VUZl30lDQFJeiSyNfzU1EjYt2QZvoBFKEwjn1lilUJw7KgqD5z7mbV7diJhT+dLFs36i0OsjXvq5kSygn8YJ3A==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/programs@5.5.1': + resolution: {integrity: sha512-7U9kn0Jsx1NuBLn5HRTFYh78MV4XN145Yc3WP/q5BlqAVNlMoU9coG5IUTJIG847TUqC1lRto3Dnpwm6T4YRpA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/promises@5.5.1': + resolution: {integrity: sha512-T9lfuUYkGykJmppEcssNiCf6yiYQxJkhiLPP+pyAc2z84/7r3UVIb2tNJk4A9sucS66pzJnVHZKcZVGUUp6wzA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-api@5.5.1': + resolution: {integrity: sha512-XWOQQPhKl06Vj0xi3RYHAc6oEQd8B82okYJ04K7N0Vvy3J4PN2cxeK7klwkjgavdcN9EVkYCChm2ADAtnztKnA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-parsed-types@5.5.1': + resolution: {integrity: sha512-HEi3G2nZqGEsa3vX6U0FrXLaqnUCg4SKIUrOe8CezD+cSFbRTOn3rCLrUmJrhVyXlHoQVaRO9mmeovk31jWxJg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-spec-types@5.5.1': + resolution: {integrity: sha512-6OFKtRpIEJQs8Jb2C4OO8KyP2h2Hy1MFhatMAoXA+0Ik8S3H+CicIuMZvGZ91mIu/tXicuOOsNNLu3HAkrakrw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-spec@5.5.1': + resolution: {integrity: sha512-m3LX2bChm3E3by4mQrH4YwCAFY57QBzuUSWqlUw7ChuZ+oLLOq7b2czi4i6L4Vna67j3eCmB3e+4tqy1j5wy7Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-subscriptions-api@5.5.1': + resolution: {integrity: sha512-5Oi7k+GdeS8xR2ly1iuSFkAv6CZqwG0Z6b1QZKbEgxadE1XGSDrhM2cn59l+bqCozUWCqh4c/A2znU/qQjROlw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-subscriptions-channel-websocket@5.5.1': + resolution: {integrity: sha512-7tGfBBrYY8TrngOyxSHoCU5shy86iA9SRMRrPSyBhEaZRAk6dnbdpmUTez7gtdVo0BCvh9nzQtUycKWSS7PnFQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-subscriptions-spec@5.5.1': + resolution: {integrity: sha512-iq+rGq5fMKP3/mKHPNB6MC8IbVW41KGZg83Us/+LE3AWOTWV1WT20KT2iH1F1ik9roi42COv/TpoZZvhKj45XQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-subscriptions@5.5.1': + resolution: {integrity: sha512-CTMy5bt/6mDh4tc6vUJms9EcuZj3xvK0/xq8IQ90rhkpYvate91RjBP+egvjgSayUg9yucU9vNuUpEjz4spM7w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-transformers@5.5.1': + resolution: {integrity: sha512-OsWqLCQdcrRJKvHiMmwFhp9noNZ4FARuMkHT5us3ustDLXaxOjF0gfqZLnMkulSLcKt7TGXqMhBV+HCo7z5M8Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-transport-http@5.5.1': + resolution: {integrity: sha512-yv8GoVSHqEV0kUJEIhkdOVkR2SvJ6yoWC51cJn2rSV7plr6huLGe0JgujCmB7uZhhaLbcbP3zxXxu9sOjsi7Fg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-types@5.5.1': + resolution: {integrity: sha512-bibTFQ7PbHJJjGJPmfYC2I+/5CRFS4O2p9WwbFraX1Keeel+nRrt/NBXIy8veP5AEn2sVJIyJPpWBRpCx1oATA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc@5.5.1': + resolution: {integrity: sha512-ku8zTUMrkCWci66PRIBC+1mXepEnZH/q1f3ck0kJZ95a06bOTl5KU7HeXWtskkyefzARJ5zvCs54AD5nxjQJ+A==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/signers@5.5.1': + resolution: {integrity: sha512-FY0IVaBT2kCAze55vEieR6hag4coqcuJ31Aw3hqRH7mv6sV8oqwuJmUrx+uFwOp1gwd5OEAzlv6N4hOOple4sQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/subscribable@5.5.1': + resolution: {integrity: sha512-9K0PsynFq0CsmK1CDi5Y2vUIJpCqkgSS5yfDN0eKPgHqEptLEaia09Kaxc90cSZDZU5mKY/zv1NBmB6Aro9zQQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/sysvars@5.5.1': + resolution: {integrity: sha512-k3Quq87Mm+geGUu1GWv6knPk0ALsfY6EKSJGw9xUJDHzY/RkYSBnh0RiOrUhtFm2TDNjOailg8/m0VHmi3reFA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/transaction-confirmation@5.5.1': + resolution: {integrity: sha512-j4mKlYPHEyu+OD7MBt3jRoX4ScFgkhZC6H65on4Fux6LMScgivPJlwnKoZMnsgxFgWds0pl+BYzSiALDsXlYtw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/transaction-messages@5.5.1': + resolution: {integrity: sha512-aXyhMCEaAp3M/4fP0akwBBQkFPr4pfwoC5CLDq999r/FUwDax2RE/h4Ic7h2Xk+JdcUwsb+rLq85Y52hq84XvQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@solana/transactions@5.5.1': + resolution: {integrity: sha512-8hHtDxtqalZ157pnx6p8k10D7J/KY/biLzfgh9R09VNLLY3Fqi7kJvJCr7M2ik3oRll56pxhraAGCC9yIT6eOA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@starknet-io/get-starknet-core@5.0.0': + resolution: {integrity: sha512-FVKYeNGHWG978482ZdCf7VQMoMn0xxHS0mWYbNB6zwkpo2yForHJwN4/EIHQkd2xp2mfAD1VcIHSZ4SLWGV1zw==} + + '@starknet-io/get-starknet-discovery@5.0.0': + resolution: {integrity: sha512-b40ZfhbisiEonxWLe/naOraZvNc1hfhy4TEs0TP/cYppfECDhBKncvvFTGu++/rm+xV3SjmSzwNQGQmIn5DMLQ==} + + '@starknet-io/get-starknet-virtual-wallet@5.0.0': + resolution: {integrity: sha512-ne9Svr0tHj7a5OJOvC82ewth/GJTa78Gal/iiiRzQmvIDpZcu+nzrPAi350RKEtErxjG5rZSPv2DLz7VBClN0Q==} + + '@starknet-io/get-starknet-wallet-standard@5.0.0': + resolution: {integrity: sha512-isDNGDlp16W24HE4IuweYXLDRZN0JbsDnazAieeKXE87Mn+jqhsjgTsMxcwWTjX7v906Bjz39FiDjGUddnr36g==} + + '@starknet-io/get-starknet-wallets@5.0.0': + resolution: {integrity: sha512-fuywFgoal4Al2KdFQCNTYgioK0ubu3cP+mM6OxE8ti78Nmd9ySlh78LwdKNXIp2Alq4kaQ5XMf6HMgkStCWhkw==} + + '@starknet-io/types-js@0.10.0': + resolution: {integrity: sha512-7ALSydz6pq3YIOpq5a7OkkxqwJciMc9Nlph0OGjhcC3xX0xH30XgizmziLyYVN10oO9+BJk8M9KbJjpzdbtRSw==} + + '@starknet-io/types-js@0.7.10': + resolution: {integrity: sha512-1VtCqX4AHWJlRRSYGSn+4X1mqolI1Tdq62IwzoU2vUuEE72S1OlEeGhpvd6XsdqXcfHmVzYfj8k1XtKBQqwo9w==} + + '@starknet-io/types-js@0.8.4': + resolution: {integrity: sha512-0RZ3TZHcLsUTQaq1JhDSCM8chnzO4/XNsSCozwDET64JK5bjFDIf2ZUkta+tl5Nlbf4usoU7uZiDI/Q57kt2SQ==} + + '@starknet-io/types-js@0.9.1': + resolution: {integrity: sha512-ngLjOFuWOI4EFij8V+nl5tgHVACr6jqgLNUQbgD+AgnTcAN33SemBPXDIsovwK1Mz1U04Cz3qjDOnTq7067ZQw==} + + '@starknet-io/types-js@0.9.2': + resolution: {integrity: sha512-vWOc0FVSn+RmabozIEWcEny1I73nDGTvOrLYJsR1x7LGA3AZmqt4i/aW69o/3i2NN5CVP8Ok6G1ayRQJKye3Wg==} + + '@starknet-react/chains@5.0.3': + resolution: {integrity: sha512-TxP391OTWgaqujT9Hu1Siljye54IHjEXrgkUuhMfxzf9sCu5q42ZzZgu9hLm0NcJgg9Fx2t75J0WB6eYmQ26fw==} + + '@starknet-react/core@5.0.3': + resolution: {integrity: sha512-BxtcYL+SPqqDo1cpzfNYcYmSY4Ifjz1O5vq5vDdjx2iHEvHYzxBMjnyacJ+JsdRlQiuLNRGInooC/yzFkMrHAQ==} + peerDependencies: + get-starknet-core: ^4.0.0 + react: ^18.0 + starknet: ^8.1.2 + + '@tanstack/query-core@5.101.4': + resolution: {integrity: sha512-gNwcvOJcRbLWPOLG/2OBm+zM+Yv+MKsXKEOWC57USuZDEsI71hEErQsiEGx5wX9rzWWkfwM0fVSPoiIFSsxfiw==} + + '@tanstack/react-query@5.101.4': + resolution: {integrity: sha512-yRg2pfOCxIs4ZJW3XYYHU/WgtD04FHSnfHlpRT7h7pR77hwkdRG4wxbKe4aq6P0RvXUTBSQpQeadS1SUYUe+KA==} + peerDependencies: + react: ^18 || ^19 + + '@turnkey/api-key-stamper@0.6.5': + resolution: {integrity: sha512-dSINHLIzYVw+ZNLwjM1wnEYFkYHPjQDSi43opCUhvow/ws6Fsn6gWkYpzbH+6Ej3rvSJTuaTwsld+dsTG/3HnA==} + engines: {node: '>=18.0.0'} + + '@turnkey/crypto@2.8.14': + resolution: {integrity: sha512-UZU+DEwhSUyyMHC9VZbp5av8NY/IJsfJ+g1E4dndQjMSAJd5NPKGS7sItlBy1ifN6wBb9JP5AcvmcfCdCfj9bw==} + engines: {node: '>=18.0.0'} + + '@turnkey/encoding@0.6.0': + resolution: {integrity: sha512-IC8qXvy36+iGAeiaVIuJvB35uU2Ld/RAWI/DRTKS+ttBej0GXhOn48Ouu5mlca4jt8ZEuwXmDVv74A8uBQclsA==} + engines: {node: '>=18.0.0'} + + '@turnkey/http@3.18.1': + resolution: {integrity: sha512-KXhDAtohx3PPRigdU0qjdgSTuomD0xl3mONly5hn8/jgrp0Gs7BKXv0OGiw/3Sj02IPmlza3SRWBKGtWyGwNmg==} + engines: {node: '>=18.0.0'} + + '@turnkey/iframe-stamper@2.11.0': + resolution: {integrity: sha512-Iyf4W4S4Hx/RVsXl07PkRTh3g5Ca+vpN6SdUbRy8lt9IQZAJel/vxAk9XMyB7utX9TJx+icSjNYHvC0XGqJ47A==} + engines: {node: '>=18.0.0'} + + '@turnkey/indexed-db-stamper@1.2.6': + resolution: {integrity: sha512-RSlCpH96e46PYgc029/TK3nE/HOW4QgKo9bXIYjoUR8J7+xkq+0Z0wjHrp27Yn3PbW8743hEppqK9jxsYc8ptA==} + engines: {node: '>=18.0.0'} + + '@turnkey/sdk-browser@5.16.1': + resolution: {integrity: sha512-AXBUJVW83nZKnSVNUH235dbsu4S+a4F0Swo25Fm/gHWKPVh4nvpT/Pr2cr6PVh3UR15p787AVUkxO9ZgtNclPw==} + engines: {node: '>=18.0.0'} + + '@turnkey/sdk-types@0.14.0': + resolution: {integrity: sha512-FLN4p3Jc3rBMvM17tgFrO4VpqkQN0RgWtLknqcqpLuNgTJ7oqgvzm42YIrzvBlW6DPsnFjVZMzc4yCfaRN7Lmg==} + engines: {node: '>=18.0.0'} + + '@turnkey/wallet-stamper@1.1.16': + resolution: {integrity: sha512-IdgoIRQr5RoiHAPnVag2QyaYg6cmmkZQs1rOig57/tQ/fXdPsC1+2660RisIAvv69ZFrArG8Z8wHaGSQMkStlw==} + + '@turnkey/webauthn-stamper@0.6.0': + resolution: {integrity: sha512-jdN17QEnn7RBykEOhtKIialWmDjnDAH8DzbyITwn8jsKcwT1TBNYge89hTUTjbdsDLBAqQw8cHujPdy0RaAqvw==} + engines: {node: '>=18.0.0'} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/node@22.7.5': + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + + '@types/prop-types@15.7.15': + resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + + '@types/react-dom@18.3.7': + resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} + peerDependencies: + '@types/react': ^18.0.0 + + '@types/react@18.3.31': + resolution: {integrity: sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + + '@vitest/expect@3.2.7': + resolution: {integrity: sha512-E8eBXaKibuvH2pSZErOjdVb5vF4PbKYcrnluBTYxEk1l/VhhwZg1kZQsdtjq+CsF5CFydf2Rdkz7jDHKSisi3w==} + + '@vitest/mocker@3.2.7': + resolution: {integrity: sha512-Trr0hYO9CM3Wj6ksWHRhK9IZpIY6wTMO5u/MqXurMxT57sWBaOPEtP3Oq60ihZuh5JsiagKfz95OcxdEP6dBrA==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.2.7': + resolution: {integrity: sha512-KUHlwqVu0sRlhCdyPdQ/wBoTfRahjUky1MubOmYw9fWfIZy1gNoHpuaaQBPAaMaVYdQYHJLurzj8ECCj5OwTqA==} + + '@vitest/runner@3.2.7': + resolution: {integrity: sha512-sB9y4ovltoQP+WaUPwmSxO9WIg9Ig694Di5PalVPsYHklAdE027mehpWF2SQSVq+k6sFgaivbTjTJwZLSHbedA==} + + '@vitest/snapshot@3.2.7': + resolution: {integrity: sha512-7C+MwShwtBSI5Buwoyg3s/iY1eHL9PKAf+O1wVh/TdnjXUtkoL/9YQtre90i4MtNXM6edP1wJ2zOBpfCyhIS7g==} + + '@vitest/spy@3.2.7': + resolution: {integrity: sha512-Q2eQGI6d2L/hBtZ0qNuKcAGid68XK6cv1xsoaIma6PaJhHPoqcEJhYpXZ/5myCMqkNgtP6UKuBhbc0nHKnrkuQ==} + + '@vitest/utils@3.2.7': + resolution: {integrity: sha512-x6BDOd7dyo3PFLY3I9/HJ25X/6OurhGXk2/B9gOZNPF7XDVjeBK4k01lQE5uvDpbuheErh91qYuE1E2OEjK3Rw==} + + '@wallet-standard/base@1.1.1': + resolution: {integrity: sha512-gggIHTtxicF9XFMQ12DkfS6NAG92Ak795JeSA7f2whAQ6Y3AkMWWuCMxSZXG2NIPN42kEaZSNVjqMsJRaJRxMQ==} + engines: {node: '>=22'} + + '@wallet-standard/features@1.1.1': + resolution: {integrity: sha512-aCWYmVeSCGViyEU5k7GMoW8zxE4Gs+C1s1Pp2XLesvSNlnZ4PMES9HUnTB3hl0b3RVj7C61yze3IWyrncqg4MA==} + engines: {node: '>=22'} + + '@wallet-standard/wallet@1.1.0': + resolution: {integrity: sha512-Gt8TnSlDZpAl+RWOOAB/kuvC7RpcdWAlFbHNoi4gsXsfaWa1QCT6LBcfIYTPdOZC9OVZUDwqGuGAcqZejDmHjg==} + engines: {node: '>=16'} + + '@wallet-standard/wallet@1.1.1': + resolution: {integrity: sha512-8WiRPaKk/wNNRZhB2eVhpR/JW7/aqTCMoZhgVUCujuzDmxxmGvsosMxdCG4NAdYkoyozAHCX8/xLtlWUn5mNdQ==} + engines: {node: '>=22'} + + '@walletconnect/core@2.23.10': + resolution: {integrity: sha512-Qq2btHEoCgruvkZCWLSrVsvg/dYbM9Z045qeClwhJR4meL32jbIRT0mKWjf0HkRc2LA82MsnszVnfuZl3yWl5A==} + engines: {node: '>=18.20.8'} + + '@walletconnect/core@2.23.7': + resolution: {integrity: sha512-yTyymn9mFaDZkUfLfZ3E9VyaSDPeHAXlrPxQRmNx2zFsEt/25GmTU2A848aomimLxZnAG2jNLhxbJ8I0gyNV+w==} + engines: {node: '>=18.20.8'} + + '@walletconnect/environment@1.0.1': + resolution: {integrity: sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==} + + '@walletconnect/ethereum-provider@2.23.10': + resolution: {integrity: sha512-OpmTS2s+zrqK7cr8yfGu62tCv6Dsoe/TI1SFYQd2tKyAaBYjrKVzZPfqbRYesgbtNKcCn8KK5Y6PrKIK52U7RQ==} + + '@walletconnect/events@1.0.1': + resolution: {integrity: sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==} + + '@walletconnect/heartbeat@1.2.2': + resolution: {integrity: sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==} + + '@walletconnect/jsonrpc-http-connection@1.0.8': + resolution: {integrity: sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==} + + '@walletconnect/jsonrpc-provider@1.0.14': + resolution: {integrity: sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==} + + '@walletconnect/jsonrpc-types@1.0.4': + resolution: {integrity: sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==} + + '@walletconnect/jsonrpc-utils@1.0.8': + resolution: {integrity: sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==} + + '@walletconnect/jsonrpc-ws-connection@1.0.16': + resolution: {integrity: sha512-G81JmsMqh5nJheE1mPst1W0WfVv0SG3N7JggwLLGnI7iuDZJq8cRJvQwLGKHn5H1WTW7DEPCo00zz5w62AbL3Q==} + + '@walletconnect/keyvaluestorage@1.1.1': + resolution: {integrity: sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==} + peerDependencies: + '@react-native-async-storage/async-storage': 1.x + peerDependenciesMeta: + '@react-native-async-storage/async-storage': + optional: true + + '@walletconnect/logger@3.0.2': + resolution: {integrity: sha512-7wR3wAwJTOmX4gbcUZcFMov8fjftY05+5cO/d4cpDD8wDzJ+cIlKdYOXaXfxHLSYeDazMXIsxMYjHYVDfkx+nA==} + + '@walletconnect/relay-api@1.0.11': + resolution: {integrity: sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==} + + '@walletconnect/relay-auth@1.1.0': + resolution: {integrity: sha512-qFw+a9uRz26jRCDgL7Q5TA9qYIgcNY8jpJzI1zAWNZ8i7mQjaijRnWFKsCHAU9CyGjvt6RKrRXyFtFOpWTVmCQ==} + + '@walletconnect/safe-json@1.0.2': + resolution: {integrity: sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==} + + '@walletconnect/sign-client@2.23.10': + resolution: {integrity: sha512-vO7DGRRmKo+rykmjVyQR1aM4I2nbk9kJ6olbxgjFRR6Jdhy+Kz+zgN7Ce5xVhPfWYVu4bV/XhOQxhvnQw7S5ng==} + + '@walletconnect/sign-client@2.23.7': + resolution: {integrity: sha512-SX61lzb1bTl/LijlcHQttnoHPBzzoY5mW9ArR6qhFtDNDTS7yr2rcH7rCngxHlYeb4rAYcWLHgbiGSrdKxl/mg==} + + '@walletconnect/time@1.0.2': + resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} + + '@walletconnect/types@2.23.10': + resolution: {integrity: sha512-XP8d41979anTrc1OJF3ISF+g81cvp1wim+ObdNnbcaT/jhwLwv+0T7rRe9VwRv+h8EaRgLyeb5YGy7oJ49vxVg==} + + '@walletconnect/types@2.23.7': + resolution: {integrity: sha512-6PAKK+iR2IntmlkCFLMAHjYeIaerCJJYRDmdRimhon0u+aNmQT+HyGM6zxDAth0rdpBD7qEvKP5IXZTE7KFUhw==} + + '@walletconnect/universal-provider@2.23.10': + resolution: {integrity: sha512-wkLcoaPA8R1Cfx5dcYmS7oMalYd0aEO6+8PNs9gZ5Zwe+zwU+6HOImL8HcCHngeMcdjLqW5aKN3Dy6NbueA3fg==} + + '@walletconnect/universal-provider@2.23.7': + resolution: {integrity: sha512-6UicU/Mhr/1bh7MNoajypz7BhigORbHpP1LFTf8FYLQGDqzmqHMqmMH2GDAImtaY2sFTi2jBvc22tLl8VMze/A==} + + '@walletconnect/utils@2.23.10': + resolution: {integrity: sha512-b1c9FRF2g7vNnz66oLW5WZD2VCMrbu9xhpmwJJwqGarBiGW7cY8NbUtS9/w2/qc0vsBVKJ/bzDn4TGjpELU6aQ==} + + '@walletconnect/utils@2.23.7': + resolution: {integrity: sha512-3p38gNrkVcIiQixVrlsWSa66Gjs5PqHOug2TxDgYUVBW5NcKjwQA08GkC6CKBQUfr5iaCtbfy6uZJW1LKSIvWQ==} + + '@walletconnect/window-getters@1.0.1': + resolution: {integrity: sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==} + + '@walletconnect/window-metadata@1.0.1': + resolution: {integrity: sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==} + + abi-wan-kanabi@2.2.4: + resolution: {integrity: sha512-0aA81FScmJCPX+8UvkXLki3X1+yPQuWxEkqXBVKltgPAK79J+NB+Lp5DouMXa7L6f+zcRlIA/6XO7BN/q9fnvg==} + hasBin: true + + abitype@1.0.6: + resolution: {integrity: sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + + abitype@1.2.3: + resolution: {integrity: sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3.22.0 || ^4.0.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + + abitype@1.3.0: + resolution: {integrity: sha512-fk6Te+bojIFrMvMZrnOO+SxCB+RUksTGOzq/60ZRvs1L+BVzvi2bqt9L3W/17ZLdZsyM1FuYf65P5nlmoiH1Bg==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3.22.0 || ^4.0.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + + aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansicolors@0.3.2: + resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + asn1js@3.0.10: + resolution: {integrity: sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==} + engines: {node: '>=12.0.0'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + async-mutex@0.5.0: + resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + axios-retry@4.5.0: + resolution: {integrity: sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==} + peerDependencies: + axios: 0.x || 1.x + + axios@1.16.0: + resolution: {integrity: sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==} + + base-x@5.0.1: + resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.11.9: + resolution: {integrity: sha512-cp447VUsGS07+n1Dqf7YSQ8maeJrjEhaDxTm1ZefbqDtypHBC5GzGMQbklR6IPR13Y8OAJRHZWEMtZipJLCttg==} + engines: {node: '>=6.0.0'} + hasBin: true + + big.js@6.2.2: + resolution: {integrity: sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==} + + blakejs@1.2.1: + resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + + borsh@2.0.0: + resolution: {integrity: sha512-kc9+BgR3zz9+cjbwM8ODoUB4fs3X3I5A/HtX7LZKxCLaMrEeDFoBpnhZY//DTS1VZBSs6S5v46RZRbZjRFspEg==} + + browserslist@4.28.7: + resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bs58@6.0.0: + resolution: {integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==} + + bs58check@4.0.0: + resolution: {integrity: sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001806: + resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + + cardinal@2.1.1: + resolution: {integrity: sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==} + hasBin: true + + cbor-extract@2.2.2: + resolution: {integrity: sha512-hlSxxI9XO2yQfe9g6msd3g4xCfDqK5T5P0fRMLuaLHhxn4ViPrm+a+MUfhrvH2W962RGxcBwEGzLQyjbDG1gng==} + hasBin: true + + cbor-js@0.1.0: + resolution: {integrity: sha512-7sQ/TvDZPl7csT1Sif9G0+MA0I0JOVah8+wWlJVQdVEgIbCzlN/ab3x+uvMNsc34TUvO6osQTAmB2ls80JX6tw==} + + cbor-x@1.6.5: + resolution: {integrity: sha512-yO64CxnSh6kp+pHNRK9IfwnMvCB+c8HvmUjQY/9l9YRF0/cAPka/tUHLwS64QqUpFCq3/OtbKziVJYXH2EaRig==} + + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@14.0.2: + resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} + engines: {node: '>=20'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-es@1.2.3: + resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} + + cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + + crossws@0.3.5: + resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} + + crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + + detect-browser@5.3.0: + resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + electron-to-chromium@1.5.399: + resolution: {integrity: sha512-lEcqhErbHjXRvd41rnWLpzbyU/IXfIYo7QwaFWmxGeLiLyY2TBCdHnWY88vB+p3ubnihRypDm66panXl7TylLA==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + encode-utf8@1.0.3: + resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-toolkit@1.44.0: + resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} + + es-toolkit@1.45.1: + resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + ethers@6.17.0: + resolution: {integrity: sha512-BpyrpIPJ3ydEVow8zGaz1DuPS7YU8DcWxuBnY9a0UA/lvAPwrMr+EPXsfrul628SRaekPNeIM4UFh/91GWZang==} + engines: {node: '>=14.0.0'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} + engines: {node: '>= 6'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-starknet-core@4.0.0: + resolution: {integrity: sha512-6pLmidQZkC3wZsrHY99grQHoGpuuXqkbSP65F8ov1/JsEI8DDLkhsAuLCKFzNOK56cJp+f1bWWfTJ57e9r5eqQ==} + deprecated: Package no longer supported. Please use @starknet-io/get-starknet-core + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + h3@1.15.11: + resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + hpke-js@1.8.0: + resolution: {integrity: sha512-N0PFQlUQsIPS9++nUNn2ZsxTPSv8pONyyrXIGZl0iiherRfS0XW1SvTd+RmepD0TN1S9zzTJkEutMIWWYt0/4w==} + engines: {node: '>=16.0.0'} + + idb-keyval@6.2.1: + resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} + + idb-keyval@6.3.0: + resolution: {integrity: sha512-um+2dgAWmYsu615EXpWVwSmapJhON0G43t3Ka/EVaohzPQXSMqKEqeDK/oIW3Ow+BXaF2PvSc+oBTFp793A5Ow==} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-retry-allowed@2.2.0: + resolution: {integrity: sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==} + engines: {node: '>=10'} + + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + + isows@1.0.7: + resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==} + peerDependencies: + ws: '*' + + jose@6.2.6: + resolution: {integrity: sha512-HwMtbJjMw8rC8dUTwCNilHJD+fxTeKM3JV1eprSmTjS41qwXSSt6exJXgyPK1QOu0jB9eDYLESRDkB3qaT3jnw==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@6.2.1: + resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + + keyvaluestorage-interface@1.0.0: + resolution: {integrity: sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==} + + lit-element@4.2.2: + resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} + + lit-html@3.3.3: + resolution: {integrity: sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==} + + lit@3.3.0: + resolution: {integrity: sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lossless-json@4.3.1: + resolution: {integrity: sha512-SqD/Bg3ZfltBJ2Z14hJ/BihnvtV553WO4g9/ePtlp4lrnl9jF3AdIJt53A/Wkg/0Li+LMfxaBqgx1MiFZdQlpQ==} + + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + + micro-packed@0.7.3: + resolution: {integrity: sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==} + + micro-sol-signer@0.5.0: + resolution: {integrity: sha512-4D5mGHuWuAC1w7HXXs+mlugw9n0hk3Gk0pFjQYkzE6zbvwEEioyb6l8375hivcqD6830/tCDCyQv+i3jfVFC+w==} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mipd@0.0.7: + resolution: {integrity: sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multiformats@9.9.0: + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} + + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp-build-optional-packages@5.1.1: + resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==} + hasBin: true + + node-mock-http@1.0.5: + resolution: {integrity: sha512-KQyt/wLjG3TAc7DOUhpqWzgd4ERxR80JOlTK5VE5R1S12IaPVN5qkj4klBce9HPG1Njuup4Sb5bljaT34lIyjw==} + + node-releases@2.0.51: + resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + engines: {node: '>=18'} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + ofetch@1.5.1: + resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + + ox@0.14.33: + resolution: {integrity: sha512-rooA/4o7bBof4Ge2VH/eovfNPb/AEEYyrNj03wggc55g5HZD8Pjs/OeWhttgjic3dDcqn0r29bDuvQEdTiUemQ==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + ox@0.4.4: + resolution: {integrity: sha512-oJPEeCDs9iNiPs6J0rTx+Y0KGeCGyCAA3zo94yZhm8G5WpOxrwUtn2Ie/Y8IyARSqqY/j9JTKA3Fc1xs1DvFnw==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + ox@0.6.9: + resolution: {integrity: sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + ox@0.9.3: + resolution: {integrity: sha512-KzyJP+fPV4uhuuqrTZyok4DC7vFzi7HLUFiUNEmpbyh59htKWkOC98IONC1zgXJPbHAhQgqs6B0Z6StCGhmQvg==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + pako@2.2.0: + resolution: {integrity: sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@10.0.0: + resolution: {integrity: sha512-eI9pKwWEix40kfvSzqEP6ldqOoBIN7dwD/o91TY5z8vQI12sAffpR/pOqAD1IVVwIVHDpHjkq0joBPdJD0rafA==} + hasBin: true + + playwright-core@1.62.1: + resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==} + engines: {node: '>=20'} + hasBin: true + + playwright@1.62.1: + resolution: {integrity: sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==} + engines: {node: '>=20'} + hasBin: true + + pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + + postcss@8.5.25: + resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} + engines: {node: ^10 || ^12 || >=14} + + preact@10.24.2: + resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} + + process-warning@5.1.0: + resolution: {integrity: sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==} + + proxy-compare@3.0.1: + resolution: {integrity: sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==} + + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + + pvtsutils@1.3.6: + resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} + + pvutils@1.1.5: + resolution: {integrity: sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==} + engines: {node: '>=16.0.0'} + + qrcode@1.5.3: + resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} + engines: {node: '>=10.13.0'} + hasBin: true + + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + redeyed@2.1.1: + resolution: {integrity: sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + + rollup@4.62.3: + resolution: {integrity: sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + sha256-uint8array@0.10.7: + resolution: {integrity: sha512-1Q6JQU4tX9NqsDGodej6pkrUVQVNapLZnvkwIhddH/JqzBZF1fSaxSWNY6sziXBE8aEa2twtGkXUrwzGeZCMpQ==} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + slow-redact@0.3.2: + resolution: {integrity: sha512-MseHyi2+E/hBRqdOi5COy6wZ7j7DxXRz9NkseavNYSvvWC06D8a5cidVZX3tcG5eCW3NIyVU4zT63hw0Q486jw==} + + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + starknet@8.9.2: + resolution: {integrity: sha512-+dp+o2w67fV6JyVOVkYeM1Ec71aORHc/JrF4VHLlfeGee0nLilooCQLE2u6hUcSGQG2x2/fvzkxYpIN+k1JBvA==} + engines: {node: '>=22'} + + starknet@9.4.2: + resolution: {integrity: sha512-NFtg077DjddHUSh8sLZ5uB149LEF4NR90FuJ0oF7+zhce7l0oG9Ubqr3H4+jHm/ghHtV+yjlv1UhEoo4SBfILA==} + engines: {node: '>=22'} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + + thread-stream@3.2.0: + resolution: {integrity: sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-mixer@6.0.4: + resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsyringe@4.10.0: + resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==} + engines: {node: '>= 6.0.0'} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + uint8arrays@3.1.1: + resolution: {integrity: sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==} + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + undici-types@7.29.0: + resolution: {integrity: sha512-vamA8dGlzMwhpyYpQp9d8vka3o4D/yn5I7ez7Or+msDA4bZ8Uh+Zy91WvWf3I73gDAkFha9JcYRqm2li0Npfgg==} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unstorage@1.17.5: + resolution: {integrity: sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==} + peerDependencies: + '@azure/app-configuration': ^1.8.0 + '@azure/cosmos': ^4.2.0 + '@azure/data-tables': ^13.3.0 + '@azure/identity': ^4.6.0 + '@azure/keyvault-secrets': ^4.9.0 + '@azure/storage-blob': ^12.26.0 + '@capacitor/preferences': ^6 || ^7 || ^8 + '@deno/kv': '>=0.9.0' + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 + '@planetscale/database': ^1.19.0 + '@upstash/redis': ^1.34.3 + '@vercel/blob': '>=0.27.1' + '@vercel/functions': ^2.2.12 || ^3.0.0 + '@vercel/kv': ^1 || ^2 || ^3 + aws4fetch: ^1.0.20 + db0: '>=0.2.1' + idb-keyval: ^6.2.1 + ioredis: ^5.4.2 + uploadthing: ^7.4.4 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@deno/kv': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/blob': + optional: true + '@vercel/functions': + optional: true + '@vercel/kv': + optional: true + aws4fetch: + optional: true + db0: + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + uploadthing: + optional: true + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + valtio@2.1.7: + resolution: {integrity: sha512-DwJhCDpujuQuKdJ2H84VbTjEJJteaSmqsuUltsfbfdbotVfNeTE4K/qc/Wi57I9x8/2ed4JNdjEna7O6PfavRg==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + react: '>=18.0.0' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + + viem@2.55.10: + resolution: {integrity: sha512-Q9Ba+/ma81U2M5o5P2AQ7Ux8rTIwmCZvUcr8rKdQ22bV0IBFHllM2m5gWDP8hFaUN2nH2oW3QG44amRazflYNQ==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@3.2.7: + resolution: {integrity: sha512-KrxIJ62Fd89gfysR4WotlgZABiz2dqFPgqGzX7s+CwsqLFomRH7777ZcrOD6+WVAh7khPQP41A+BKbpcJFrdEg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.7 + '@vitest/ui': 3.2.7 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + ws@7.5.13: + resolution: {integrity: sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.21.1: + resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} + engines: {node: '>=12'} + + zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zustand@5.0.3: + resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + +snapshots: + + '@adraffy/ens-normalize@1.11.1': {} + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.7 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.29.7': {} + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 + + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + + '@babel/traverse@7.29.8': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@base-org/account@2.4.0(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@coinbase/cdp-sdk': 1.54.0(typescript@5.9.3) + '@noble/hashes': 1.4.0 + clsx: 1.2.1 + eventemitter3: 5.0.1 + idb-keyval: 6.2.1 + ox: 0.6.9(typescript@5.9.3)(zod@3.25.76) + preact: 10.24.2 + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + zustand: 5.0.3(@types/react@18.3.31)(react@18.3.1) + transitivePeerDependencies: + - '@types/react' + - '@x402/core' + - '@x402/evm' + - '@x402/extensions' + - '@x402/svm' + - bufferutil + - debug + - fastestsmallesttextencoderdecoder + - immer + - react + - typescript + - use-sync-external-store + - utf-8-validate + - zod + optional: true + + '@cartridge/connector@0.13.16(@starknet-react/core@5.0.3(get-starknet-core@4.0.0)(react@18.3.1)(starknet@9.4.2(typescript@5.9.3)(zod@3.25.76))(typescript@5.9.3))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@cartridge/controller': 0.13.16(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@starknet-react/core': 5.0.3(get-starknet-core@4.0.0)(react@18.3.1)(starknet@9.4.2(typescript@5.9.3)(zod@3.25.76))(typescript@5.9.3) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@x402/core' + - '@x402/evm' + - '@x402/extensions' + - '@x402/svm' + - aws4fetch + - bufferutil + - db0 + - debug + - encoding + - fastestsmallesttextencoderdecoder + - immer + - ioredis + - react + - react-dom + - typescript + - uploadthing + - use-sync-external-store + - utf-8-validate + - zod + + '@cartridge/controller-wasm@0.10.1': {} + + '@cartridge/controller@0.13.16(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@cartridge/controller-wasm': 0.10.1 + '@cartridge/penpal': 6.2.4 + '@starknet-io/get-starknet-core': 5.0.0(typescript@5.9.3)(zod@3.25.76) + '@starknet-io/types-js': 0.9.1 + '@turnkey/sdk-browser': 5.16.1(typescript@5.9.3)(zod@3.25.76) + '@wallet-standard/wallet': 1.1.1 + '@walletconnect/ethereum-provider': 2.23.10(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + bs58: 6.0.0 + cbor-x: 1.6.5 + ethers: 6.17.0 + micro-sol-signer: 0.5.0 + mipd: 0.0.7(typescript@5.9.3) + open: 10.2.0 + starknet: 8.9.2 + optionalDependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@x402/core' + - '@x402/evm' + - '@x402/extensions' + - '@x402/svm' + - aws4fetch + - bufferutil + - db0 + - debug + - encoding + - fastestsmallesttextencoderdecoder + - immer + - ioredis + - typescript + - uploadthing + - use-sync-external-store + - utf-8-validate + - zod + + '@cartridge/penpal@6.2.4': {} + + '@cbor-extract/cbor-extract-darwin-arm64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-darwin-x64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-linux-arm64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-linux-arm@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-linux-x64@2.2.2': + optional: true + + '@cbor-extract/cbor-extract-win32-x64@2.2.2': + optional: true + + '@coinbase/cdp-sdk@1.54.0(typescript@5.9.3)': + dependencies: + '@solana-program/system': 0.10.0(@solana/kit@5.5.1(typescript@5.9.3)) + '@solana-program/token': 0.9.0(@solana/kit@5.5.1(typescript@5.9.3)) + '@solana/kit': 5.5.1(typescript@5.9.3) + abitype: 1.0.6(typescript@5.9.3)(zod@3.25.76) + axios: 1.16.0 + axios-retry: 4.5.0(axios@1.16.0) + bs58: 6.0.0 + jose: 6.2.6 + md5: 2.3.0 + uncrypto: 0.1.3 + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + zod: 3.25.76 + transitivePeerDependencies: + - bufferutil + - debug + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + optional: true + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@hpke/chacha20poly1305@1.8.0': + dependencies: + '@hpke/common': 1.10.1 + + '@hpke/common@1.10.1': {} + + '@hpke/core@1.9.0': + dependencies: + '@hpke/common': 1.10.1 + + '@hpke/dhkem-x25519@1.8.0': + dependencies: + '@hpke/common': 1.10.1 + + '@hpke/dhkem-x448@1.8.0': + dependencies: + '@hpke/common': 1.10.1 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@lit-labs/ssr-dom-shim@1.6.0': {} + + '@lit/react@1.0.8(@types/react@18.3.31)': + dependencies: + '@types/react': 18.3.31 + optional: true + + '@lit/reactive-element@2.1.2': + dependencies: + '@lit-labs/ssr-dom-shim': 1.6.0 + + '@module-federation/error-codes@0.12.0': {} + + '@module-federation/runtime-core@0.12.0': + dependencies: + '@module-federation/error-codes': 0.12.0 + '@module-federation/sdk': 0.12.0 + + '@module-federation/runtime@0.12.0': + dependencies: + '@module-federation/error-codes': 0.12.0 + '@module-federation/runtime-core': 0.12.0 + '@module-federation/sdk': 0.12.0 + + '@module-federation/sdk@0.12.0': {} + + '@msgpack/msgpack@3.1.3': {} + + '@noble/ciphers@1.3.0': {} + + '@noble/curves@1.2.0': + dependencies: + '@noble/hashes': 1.3.2 + + '@noble/curves@1.7.0': + dependencies: + '@noble/hashes': 1.6.0 + + '@noble/curves@1.8.0': + dependencies: + '@noble/hashes': 1.7.0 + + '@noble/curves@1.9.0': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/curves@1.9.1': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/curves@1.9.7': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/hashes@1.3.2': {} + + '@noble/hashes@1.4.0': + optional: true + + '@noble/hashes@1.6.0': {} + + '@noble/hashes@1.6.1': {} + + '@noble/hashes@1.7.0': {} + + '@noble/hashes@1.8.0': {} + + '@peculiar/asn1-cms@2.8.0': + dependencies: + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-x509-attr': 2.8.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-csr@2.8.0': + dependencies: + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-ecc@2.8.0': + dependencies: + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-pfx@2.8.0': + dependencies: + '@peculiar/asn1-cms': 2.8.0 + '@peculiar/asn1-pkcs8': 2.8.0 + '@peculiar/asn1-rsa': 2.8.0 + '@peculiar/asn1-schema': 2.8.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-pkcs8@2.8.0': + dependencies: + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-pkcs9@2.8.0': + dependencies: + '@peculiar/asn1-cms': 2.8.0 + '@peculiar/asn1-pfx': 2.8.0 + '@peculiar/asn1-pkcs8': 2.8.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-x509-attr': 2.8.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-rsa@2.8.0': + dependencies: + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-schema@2.8.0': + dependencies: + '@peculiar/utils': 2.0.3 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-x509-attr@2.8.0': + dependencies: + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/asn1-x509@2.8.0': + dependencies: + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/utils': 2.0.3 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/utils@2.0.3': + dependencies: + tslib: 2.8.1 + + '@peculiar/x509@1.12.3': + dependencies: + '@peculiar/asn1-cms': 2.8.0 + '@peculiar/asn1-csr': 2.8.0 + '@peculiar/asn1-ecc': 2.8.0 + '@peculiar/asn1-pkcs9': 2.8.0 + '@peculiar/asn1-rsa': 2.8.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + pvtsutils: 1.3.6 + reflect-metadata: 0.2.2 + tslib: 2.8.1 + tsyringe: 4.10.0 + + '@phosphor-icons/webcomponents@2.1.5': + dependencies: + lit: 3.3.0 + + '@reown/appkit-common@1.8.19(typescript@5.9.3)(zod@3.22.4)': + dependencies: + big.js: 6.2.2 + dayjs: 1.11.13 + viem: 2.55.10(typescript@5.9.3)(zod@3.22.4) + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + + '@reown/appkit-common@1.8.19(typescript@5.9.3)(zod@3.25.76)': + dependencies: + big.js: 6.2.2 + dayjs: 1.11.13 + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + + '@reown/appkit-controllers@1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@reown/appkit-common': 1.8.19(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-wallet': 1.8.19(typescript@5.9.3) + '@walletconnect/universal-provider': 2.23.7(typescript@5.9.3)(zod@3.25.76) + valtio: 2.1.7(@types/react@18.3.31)(react@18.3.1) + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - zod + + '@reown/appkit-pay@1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@reown/appkit-common': 1.8.19(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-controllers': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-ui': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-utils': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.7(@types/react@18.3.31)(react@18.3.1))(zod@3.25.76) + lit: 3.3.0 + valtio: 2.1.7(@types/react@18.3.31)(react@18.3.1) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@x402/core' + - '@x402/evm' + - '@x402/extensions' + - '@x402/svm' + - aws4fetch + - bufferutil + - db0 + - debug + - encoding + - fastestsmallesttextencoderdecoder + - immer + - ioredis + - react + - typescript + - uploadthing + - use-sync-external-store + - utf-8-validate + - zod + + '@reown/appkit-polyfills@1.8.19': + dependencies: + buffer: 6.0.3 + + '@reown/appkit-scaffold-ui@1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.7(@types/react@18.3.31)(react@18.3.1))(zod@3.25.76)': + dependencies: + '@reown/appkit-common': 1.8.19(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-controllers': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-pay': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-ui': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-utils': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.7(@types/react@18.3.31)(react@18.3.1))(zod@3.25.76) + '@reown/appkit-wallet': 1.8.19(typescript@5.9.3) + lit: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@x402/core' + - '@x402/evm' + - '@x402/extensions' + - '@x402/svm' + - aws4fetch + - bufferutil + - db0 + - debug + - encoding + - fastestsmallesttextencoderdecoder + - immer + - ioredis + - react + - typescript + - uploadthing + - use-sync-external-store + - utf-8-validate + - valtio + - zod + + '@reown/appkit-ui@1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@phosphor-icons/webcomponents': 2.1.5 + '@reown/appkit-common': 1.8.19(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-controllers': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-wallet': 1.8.19(typescript@5.9.3) + lit: 3.3.0 + qrcode: 1.5.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - zod + + '@reown/appkit-utils@1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.7(@types/react@18.3.31)(react@18.3.1))(zod@3.25.76)': + dependencies: + '@reown/appkit-common': 1.8.19(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-controllers': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-polyfills': 1.8.19 + '@reown/appkit-wallet': 1.8.19(typescript@5.9.3) + '@wallet-standard/wallet': 1.1.0 + '@walletconnect/logger': 3.0.2 + '@walletconnect/universal-provider': 2.23.7(typescript@5.9.3)(zod@3.25.76) + valtio: 2.1.7(@types/react@18.3.31)(react@18.3.1) + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + optionalDependencies: + '@base-org/account': 2.4.0(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@safe-global/safe-apps-provider': 0.18.6(typescript@5.9.3)(zod@3.25.76) + '@safe-global/safe-apps-sdk': 9.1.0(typescript@5.9.3)(zod@3.25.76) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@x402/core' + - '@x402/evm' + - '@x402/extensions' + - '@x402/svm' + - aws4fetch + - bufferutil + - db0 + - debug + - encoding + - fastestsmallesttextencoderdecoder + - immer + - ioredis + - react + - typescript + - uploadthing + - use-sync-external-store + - utf-8-validate + - zod + + '@reown/appkit-wallet@1.8.19(typescript@5.9.3)': + dependencies: + '@reown/appkit-common': 1.8.19(typescript@5.9.3)(zod@3.22.4) + '@reown/appkit-polyfills': 1.8.19 + '@walletconnect/logger': 3.0.2 + zod: 3.22.4 + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + + '@reown/appkit@1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@reown/appkit-common': 1.8.19(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-controllers': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-pay': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-polyfills': 1.8.19 + '@reown/appkit-scaffold-ui': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.7(@types/react@18.3.31)(react@18.3.1))(zod@3.25.76) + '@reown/appkit-ui': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-utils': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.7(@types/react@18.3.31)(react@18.3.1))(zod@3.25.76) + '@reown/appkit-wallet': 1.8.19(typescript@5.9.3) + '@walletconnect/universal-provider': 2.23.7(typescript@5.9.3)(zod@3.25.76) + bs58: 6.0.0 + semver: 7.7.2 + valtio: 2.1.7(@types/react@18.3.31)(react@18.3.1) + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + optionalDependencies: + '@lit/react': 1.0.8(@types/react@18.3.31) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@x402/core' + - '@x402/evm' + - '@x402/extensions' + - '@x402/svm' + - aws4fetch + - bufferutil + - db0 + - debug + - encoding + - fastestsmallesttextencoderdecoder + - immer + - ioredis + - react + - typescript + - uploadthing + - use-sync-external-store + - utf-8-validate + - zod + + '@rolldown/pluginutils@1.0.0-beta.27': {} + + '@rollup/rollup-android-arm-eabi@4.62.3': + optional: true + + '@rollup/rollup-android-arm64@4.62.3': + optional: true + + '@rollup/rollup-darwin-arm64@4.62.3': + optional: true + + '@rollup/rollup-darwin-x64@4.62.3': + optional: true + + '@rollup/rollup-freebsd-arm64@4.62.3': + optional: true + + '@rollup/rollup-freebsd-x64@4.62.3': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.62.3': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.62.3': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-x64-musl@4.62.3': + optional: true + + '@rollup/rollup-openbsd-x64@4.62.3': + optional: true + + '@rollup/rollup-openharmony-arm64@4.62.3': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.62.3': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.62.3': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.62.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.62.3': + optional: true + + '@safe-global/safe-apps-provider@0.18.6(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@safe-global/safe-apps-sdk': 9.1.0(typescript@5.9.3)(zod@3.25.76) + events: 3.3.0 + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + optional: true + + '@safe-global/safe-apps-sdk@9.1.0(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@safe-global/safe-gateway-typescript-sdk': 3.23.1 + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + optional: true + + '@safe-global/safe-gateway-typescript-sdk@3.23.1': + optional: true + + '@scure/base@1.2.6': {} + + '@scure/bip32@1.7.0': + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + + '@scure/bip39@1.6.0': + dependencies: + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + + '@scure/starknet@1.1.0': + dependencies: + '@noble/curves': 1.7.0 + '@noble/hashes': 1.6.1 + + '@solana-program/system@0.10.0(@solana/kit@5.5.1(typescript@5.9.3))': + dependencies: + '@solana/kit': 5.5.1(typescript@5.9.3) + optional: true + + '@solana-program/token@0.9.0(@solana/kit@5.5.1(typescript@5.9.3))': + dependencies: + '@solana/kit': 5.5.1(typescript@5.9.3) + optional: true + + '@solana/accounts@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/addresses@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/assertions': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/nominal-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/assertions@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/codecs-core@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/codecs-data-structures@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/codecs-numbers@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/codecs-strings@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/codecs@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/options': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/errors@5.5.1(typescript@5.9.3)': + dependencies: + chalk: 5.6.2 + commander: 14.0.2 + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/fast-stable-stringify@5.5.1(typescript@5.9.3)': + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/functional@5.5.1(typescript@5.9.3)': + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/instruction-plans@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/instructions': 5.5.1(typescript@5.9.3) + '@solana/keys': 5.5.1(typescript@5.9.3) + '@solana/promises': 5.5.1(typescript@5.9.3) + '@solana/transaction-messages': 5.5.1(typescript@5.9.3) + '@solana/transactions': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/instructions@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/keys@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/assertions': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/nominal-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/kit@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/accounts': 5.5.1(typescript@5.9.3) + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/codecs': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/functional': 5.5.1(typescript@5.9.3) + '@solana/instruction-plans': 5.5.1(typescript@5.9.3) + '@solana/instructions': 5.5.1(typescript@5.9.3) + '@solana/keys': 5.5.1(typescript@5.9.3) + '@solana/offchain-messages': 5.5.1(typescript@5.9.3) + '@solana/plugin-core': 5.5.1(typescript@5.9.3) + '@solana/programs': 5.5.1(typescript@5.9.3) + '@solana/rpc': 5.5.1(typescript@5.9.3) + '@solana/rpc-api': 5.5.1(typescript@5.9.3) + '@solana/rpc-parsed-types': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) + '@solana/rpc-subscriptions': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + '@solana/signers': 5.5.1(typescript@5.9.3) + '@solana/sysvars': 5.5.1(typescript@5.9.3) + '@solana/transaction-confirmation': 5.5.1(typescript@5.9.3) + '@solana/transaction-messages': 5.5.1(typescript@5.9.3) + '@solana/transactions': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - bufferutil + - fastestsmallesttextencoderdecoder + - utf-8-validate + optional: true + + '@solana/nominal-types@5.5.1(typescript@5.9.3)': + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/offchain-messages@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/keys': 5.5.1(typescript@5.9.3) + '@solana/nominal-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/options@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/plugin-core@5.5.1(typescript@5.9.3)': + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/programs@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/promises@5.5.1(typescript@5.9.3)': + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/rpc-api@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/keys': 5.5.1(typescript@5.9.3) + '@solana/rpc-parsed-types': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec': 5.5.1(typescript@5.9.3) + '@solana/rpc-transformers': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + '@solana/transaction-messages': 5.5.1(typescript@5.9.3) + '@solana/transactions': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/rpc-parsed-types@5.5.1(typescript@5.9.3)': + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/rpc-spec-types@5.5.1(typescript@5.9.3)': + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/rpc-spec@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/rpc-subscriptions-api@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/keys': 5.5.1(typescript@5.9.3) + '@solana/rpc-subscriptions-spec': 5.5.1(typescript@5.9.3) + '@solana/rpc-transformers': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + '@solana/transaction-messages': 5.5.1(typescript@5.9.3) + '@solana/transactions': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/rpc-subscriptions-channel-websocket@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/functional': 5.5.1(typescript@5.9.3) + '@solana/rpc-subscriptions-spec': 5.5.1(typescript@5.9.3) + '@solana/subscribable': 5.5.1(typescript@5.9.3) + ws: 8.21.1 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + optional: true + + '@solana/rpc-subscriptions-spec@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/promises': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) + '@solana/subscribable': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/rpc-subscriptions@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/fast-stable-stringify': 5.5.1(typescript@5.9.3) + '@solana/functional': 5.5.1(typescript@5.9.3) + '@solana/promises': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) + '@solana/rpc-subscriptions-api': 5.5.1(typescript@5.9.3) + '@solana/rpc-subscriptions-channel-websocket': 5.5.1(typescript@5.9.3) + '@solana/rpc-subscriptions-spec': 5.5.1(typescript@5.9.3) + '@solana/rpc-transformers': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + '@solana/subscribable': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - bufferutil + - fastestsmallesttextencoderdecoder + - utf-8-validate + optional: true + + '@solana/rpc-transformers@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/functional': 5.5.1(typescript@5.9.3) + '@solana/nominal-types': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/rpc-transport-http@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) + undici-types: 7.29.0 + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/rpc-types@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/nominal-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/rpc@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/fast-stable-stringify': 5.5.1(typescript@5.9.3) + '@solana/functional': 5.5.1(typescript@5.9.3) + '@solana/rpc-api': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec': 5.5.1(typescript@5.9.3) + '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) + '@solana/rpc-transformers': 5.5.1(typescript@5.9.3) + '@solana/rpc-transport-http': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/signers@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/instructions': 5.5.1(typescript@5.9.3) + '@solana/keys': 5.5.1(typescript@5.9.3) + '@solana/nominal-types': 5.5.1(typescript@5.9.3) + '@solana/offchain-messages': 5.5.1(typescript@5.9.3) + '@solana/transaction-messages': 5.5.1(typescript@5.9.3) + '@solana/transactions': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/subscribable@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + optional: true + + '@solana/sysvars@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/accounts': 5.5.1(typescript@5.9.3) + '@solana/codecs': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/transaction-confirmation@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/keys': 5.5.1(typescript@5.9.3) + '@solana/promises': 5.5.1(typescript@5.9.3) + '@solana/rpc': 5.5.1(typescript@5.9.3) + '@solana/rpc-subscriptions': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + '@solana/transaction-messages': 5.5.1(typescript@5.9.3) + '@solana/transactions': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - bufferutil + - fastestsmallesttextencoderdecoder + - utf-8-validate + optional: true + + '@solana/transaction-messages@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/functional': 5.5.1(typescript@5.9.3) + '@solana/instructions': 5.5.1(typescript@5.9.3) + '@solana/nominal-types': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@solana/transactions@5.5.1(typescript@5.9.3)': + dependencies: + '@solana/addresses': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/functional': 5.5.1(typescript@5.9.3) + '@solana/instructions': 5.5.1(typescript@5.9.3) + '@solana/keys': 5.5.1(typescript@5.9.3) + '@solana/nominal-types': 5.5.1(typescript@5.9.3) + '@solana/rpc-types': 5.5.1(typescript@5.9.3) + '@solana/transaction-messages': 5.5.1(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + optional: true + + '@starknet-io/get-starknet-core@5.0.0(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@starknet-io/get-starknet-discovery': 5.0.0(typescript@5.9.3)(zod@3.25.76) + '@starknet-io/get-starknet-virtual-wallet': 5.0.0(typescript@5.9.3)(zod@3.25.76) + '@starknet-io/get-starknet-wallet-standard': 5.0.0(typescript@5.9.3)(zod@3.25.76) + '@starknet-io/get-starknet-wallets': 5.0.0 + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + + '@starknet-io/get-starknet-discovery@5.0.0(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@starknet-io/get-starknet-virtual-wallet': 5.0.0(typescript@5.9.3)(zod@3.25.76) + '@starknet-io/get-starknet-wallet-standard': 5.0.0(typescript@5.9.3)(zod@3.25.76) + '@starknet-io/types-js': 0.7.10 + '@wallet-standard/base': 1.1.1 + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + + '@starknet-io/get-starknet-virtual-wallet@5.0.0(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@module-federation/runtime': 0.12.0 + '@starknet-io/get-starknet-wallet-standard': 5.0.0(typescript@5.9.3)(zod@3.25.76) + '@starknet-io/types-js': 0.7.10 + '@wallet-standard/base': 1.1.1 + '@wallet-standard/features': 1.1.1 + async-mutex: 0.5.0 + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + + '@starknet-io/get-starknet-wallet-standard@5.0.0(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@starknet-io/types-js': 0.7.10 + '@wallet-standard/base': 1.1.1 + '@wallet-standard/features': 1.1.1 + ox: 0.4.4(typescript@5.9.3)(zod@3.25.76) + transitivePeerDependencies: + - typescript + - zod + + '@starknet-io/get-starknet-wallets@5.0.0': {} + + '@starknet-io/types-js@0.10.0': {} + + '@starknet-io/types-js@0.7.10': {} + + '@starknet-io/types-js@0.8.4': {} + + '@starknet-io/types-js@0.9.1': {} + + '@starknet-io/types-js@0.9.2': {} + + '@starknet-react/chains@5.0.3': {} + + '@starknet-react/core@5.0.3(get-starknet-core@4.0.0)(react@18.3.1)(starknet@9.4.2(typescript@5.9.3)(zod@3.25.76))(typescript@5.9.3)': + dependencies: + '@starknet-io/types-js': 0.7.10 + '@starknet-react/chains': 5.0.3 + '@tanstack/react-query': 5.101.4(react@18.3.1) + abi-wan-kanabi: 2.2.4 + eventemitter3: 5.0.4 + get-starknet-core: 4.0.0 + react: 18.3.1 + starknet: 9.4.2(typescript@5.9.3)(zod@3.25.76) + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + zod: 3.25.76 + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + + '@tanstack/query-core@5.101.4': {} + + '@tanstack/react-query@5.101.4(react@18.3.1)': + dependencies: + '@tanstack/query-core': 5.101.4 + react: 18.3.1 + + '@turnkey/api-key-stamper@0.6.5': + dependencies: + '@noble/curves': 1.9.7 + '@turnkey/crypto': 2.8.14 + '@turnkey/encoding': 0.6.0 + sha256-uint8array: 0.10.7 + + '@turnkey/crypto@2.8.14': + dependencies: + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.0 + '@noble/hashes': 1.8.0 + '@peculiar/x509': 1.12.3 + '@turnkey/encoding': 0.6.0 + '@turnkey/sdk-types': 0.14.0 + borsh: 2.0.0 + cbor-js: 0.1.0 + + '@turnkey/encoding@0.6.0': + dependencies: + bs58: 6.0.0 + bs58check: 4.0.0 + + '@turnkey/http@3.18.1': + dependencies: + '@turnkey/api-key-stamper': 0.6.5 + '@turnkey/encoding': 0.6.0 + '@turnkey/webauthn-stamper': 0.6.0 + cross-fetch: 3.2.0 + transitivePeerDependencies: + - encoding + + '@turnkey/iframe-stamper@2.11.0': {} + + '@turnkey/indexed-db-stamper@1.2.6': + dependencies: + '@turnkey/api-key-stamper': 0.6.5 + '@turnkey/encoding': 0.6.0 + + '@turnkey/sdk-browser@5.16.1(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@turnkey/api-key-stamper': 0.6.5 + '@turnkey/crypto': 2.8.14 + '@turnkey/encoding': 0.6.0 + '@turnkey/http': 3.18.1 + '@turnkey/iframe-stamper': 2.11.0 + '@turnkey/indexed-db-stamper': 1.2.6 + '@turnkey/sdk-types': 0.14.0 + '@turnkey/wallet-stamper': 1.1.16(typescript@5.9.3)(zod@3.25.76) + '@turnkey/webauthn-stamper': 0.6.0 + buffer: 6.0.3 + cross-fetch: 3.2.0 + hpke-js: 1.8.0 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + - zod + + '@turnkey/sdk-types@0.14.0': {} + + '@turnkey/wallet-stamper@1.1.16(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@turnkey/crypto': 2.8.14 + '@turnkey/encoding': 0.6.0 + optionalDependencies: + viem: 2.55.10(typescript@5.9.3)(zod@3.25.76) + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + + '@turnkey/webauthn-stamper@0.6.0': + dependencies: + sha256-uint8array: 0.10.7 + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.8 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.8 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.9': {} + + '@types/node@22.7.5': + dependencies: + undici-types: 6.19.8 + + '@types/prop-types@15.7.15': {} + + '@types/react-dom@18.3.7(@types/react@18.3.31)': + dependencies: + '@types/react': 18.3.31 + + '@types/react@18.3.31': + dependencies: + '@types/prop-types': 15.7.15 + csstype: 3.2.3 + + '@types/trusted-types@2.0.7': {} + + '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@22.7.5))': + dependencies: + '@babel/core': 7.29.7 + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 5.4.21(@types/node@22.7.5) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@3.2.7': + dependencies: + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.7 + '@vitest/utils': 3.2.7 + chai: 5.3.3 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.7(vite@5.4.21(@types/node@22.7.5))': + dependencies: + '@vitest/spy': 3.2.7 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 5.4.21(@types/node@22.7.5) + + '@vitest/pretty-format@3.2.7': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.7': + dependencies: + '@vitest/utils': 3.2.7 + pathe: 2.0.3 + strip-literal: 3.1.0 + + '@vitest/snapshot@3.2.7': + dependencies: + '@vitest/pretty-format': 3.2.7 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@3.2.7': + dependencies: + tinyspy: 4.0.4 + + '@vitest/utils@3.2.7': + dependencies: + '@vitest/pretty-format': 3.2.7 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + + '@wallet-standard/base@1.1.1': {} + + '@wallet-standard/features@1.1.1': + dependencies: + '@wallet-standard/base': 1.1.1 + + '@wallet-standard/wallet@1.1.0': + dependencies: + '@wallet-standard/base': 1.1.1 + + '@wallet-standard/wallet@1.1.1': + dependencies: + '@wallet-standard/base': 1.1.1 + + '@walletconnect/core@2.23.10(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.16 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 3.0.2 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.23.10 + '@walletconnect/utils': 2.23.10(typescript@5.9.3)(zod@3.25.76) + '@walletconnect/window-getters': 1.0.1 + es-toolkit: 1.45.1 + events: 3.3.0 + uint8arrays: 3.1.1 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + + '@walletconnect/core@2.23.7(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.16 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 3.0.2 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.23.7 + '@walletconnect/utils': 2.23.7(typescript@5.9.3)(zod@3.25.76) + '@walletconnect/window-getters': 1.0.1 + es-toolkit: 1.44.0 + events: 3.3.0 + uint8arrays: 3.1.1 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + + '@walletconnect/environment@1.0.1': + dependencies: + tslib: 1.14.1 + + '@walletconnect/ethereum-provider@2.23.10(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@reown/appkit': 1.8.19(@types/react@18.3.31)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/sign-client': 2.23.10(typescript@5.9.3)(zod@3.25.76) + '@walletconnect/types': 2.23.10 + '@walletconnect/universal-provider': 2.23.10(typescript@5.9.3)(zod@3.25.76) + '@walletconnect/utils': 2.23.10(typescript@5.9.3)(zod@3.25.76) + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@x402/core' + - '@x402/evm' + - '@x402/extensions' + - '@x402/svm' + - aws4fetch + - bufferutil + - db0 + - debug + - encoding + - fastestsmallesttextencoderdecoder + - immer + - ioredis + - react + - typescript + - uploadthing + - use-sync-external-store + - utf-8-validate + - zod + + '@walletconnect/events@1.0.1': + dependencies: + keyvaluestorage-interface: 1.0.0 + tslib: 1.14.1 + + '@walletconnect/heartbeat@1.2.2': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/time': 1.0.2 + events: 3.3.0 + + '@walletconnect/jsonrpc-http-connection@1.0.8': + dependencies: + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/safe-json': 1.0.2 + cross-fetch: 3.2.0 + events: 3.3.0 + transitivePeerDependencies: + - encoding + + '@walletconnect/jsonrpc-provider@1.0.14': + dependencies: + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/safe-json': 1.0.2 + events: 3.3.0 + + '@walletconnect/jsonrpc-types@1.0.4': + dependencies: + events: 3.3.0 + keyvaluestorage-interface: 1.0.0 + + '@walletconnect/jsonrpc-utils@1.0.8': + dependencies: + '@walletconnect/environment': 1.0.1 + '@walletconnect/jsonrpc-types': 1.0.4 + tslib: 1.14.1 + + '@walletconnect/jsonrpc-ws-connection@1.0.16': + dependencies: + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/safe-json': 1.0.2 + events: 3.3.0 + ws: 7.5.13 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@walletconnect/keyvaluestorage@1.1.1': + dependencies: + '@walletconnect/safe-json': 1.0.2 + idb-keyval: 6.3.0 + unstorage: 1.17.5(idb-keyval@6.3.0) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - ioredis + - uploadthing + + '@walletconnect/logger@3.0.2': + dependencies: + '@walletconnect/safe-json': 1.0.2 + pino: 10.0.0 + + '@walletconnect/relay-api@1.0.11': + dependencies: + '@walletconnect/jsonrpc-types': 1.0.4 + + '@walletconnect/relay-auth@1.1.0': + dependencies: + '@noble/curves': 1.8.0 + '@noble/hashes': 1.7.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + uint8arrays: 3.1.1 + + '@walletconnect/safe-json@1.0.2': + dependencies: + tslib: 1.14.1 + + '@walletconnect/sign-client@2.23.10(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@walletconnect/core': 2.23.10(typescript@5.9.3)(zod@3.25.76) + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 3.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.23.10 + '@walletconnect/utils': 2.23.10(typescript@5.9.3)(zod@3.25.76) + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + + '@walletconnect/sign-client@2.23.7(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@walletconnect/core': 2.23.7(typescript@5.9.3)(zod@3.25.76) + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 3.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.23.7 + '@walletconnect/utils': 2.23.7(typescript@5.9.3)(zod@3.25.76) + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + + '@walletconnect/time@1.0.2': + dependencies: + tslib: 1.14.1 + + '@walletconnect/types@2.23.10': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 3.0.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - ioredis + - uploadthing + + '@walletconnect/types@2.23.7': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 3.0.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - ioredis + - uploadthing + + '@walletconnect/universal-provider@2.23.10(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/jsonrpc-http-connection': 1.0.8 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 3.0.2 + '@walletconnect/sign-client': 2.23.10(typescript@5.9.3)(zod@3.25.76) + '@walletconnect/types': 2.23.10 + '@walletconnect/utils': 2.23.10(typescript@5.9.3)(zod@3.25.76) + es-toolkit: 1.45.1 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + + '@walletconnect/universal-provider@2.23.7(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/jsonrpc-http-connection': 1.0.8 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 3.0.2 + '@walletconnect/sign-client': 2.23.7(typescript@5.9.3)(zod@3.25.76) + '@walletconnect/types': 2.23.7 + '@walletconnect/utils': 2.23.7(typescript@5.9.3)(zod@3.25.76) + es-toolkit: 1.44.0 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + + '@walletconnect/utils@2.23.10(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@msgpack/msgpack': 3.1.3 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 3.0.2 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.23.10 + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + blakejs: 1.2.1 + detect-browser: 5.3.0 + ox: 0.9.3(typescript@5.9.3)(zod@3.25.76) + uint8arrays: 3.1.1 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - ioredis + - typescript + - uploadthing + - zod + + '@walletconnect/utils@2.23.7(typescript@5.9.3)(zod@3.25.76)': + dependencies: + '@msgpack/msgpack': 3.1.3 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 3.0.2 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.23.7 + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + blakejs: 1.2.1 + detect-browser: 5.3.0 + ox: 0.9.3(typescript@5.9.3)(zod@3.25.76) + uint8arrays: 3.1.1 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - ioredis + - typescript + - uploadthing + - zod + + '@walletconnect/window-getters@1.0.1': + dependencies: + tslib: 1.14.1 + + '@walletconnect/window-metadata@1.0.1': + dependencies: + '@walletconnect/window-getters': 1.0.1 + tslib: 1.14.1 + + abi-wan-kanabi@2.2.4: + dependencies: + ansicolors: 0.3.2 + cardinal: 2.1.1 + fs-extra: 10.1.0 + yargs: 17.7.3 + + abitype@1.0.6(typescript@5.9.3)(zod@3.25.76): + optionalDependencies: + typescript: 5.9.3 + zod: 3.25.76 + optional: true + + abitype@1.2.3(typescript@5.9.3)(zod@3.22.4): + optionalDependencies: + typescript: 5.9.3 + zod: 3.22.4 + + abitype@1.2.3(typescript@5.9.3)(zod@3.25.76): + optionalDependencies: + typescript: 5.9.3 + zod: 3.25.76 + + abitype@1.3.0(typescript@5.9.3)(zod@3.25.76): + optionalDependencies: + typescript: 5.9.3 + zod: 3.25.76 + + aes-js@4.0.0-beta.5: {} + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansicolors@0.3.2: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + asn1js@3.0.10: + dependencies: + pvtsutils: 1.3.6 + pvutils: 1.1.5 + tslib: 2.8.1 + + assertion-error@2.0.1: {} + + async-mutex@0.5.0: + dependencies: + tslib: 2.8.1 + + asynckit@0.4.0: + optional: true + + atomic-sleep@1.0.0: {} + + axios-retry@4.5.0(axios@1.16.0): + dependencies: + axios: 1.16.0 + is-retry-allowed: 2.2.0 + optional: true + + axios@1.16.0: + dependencies: + follow-redirects: 1.16.0 + form-data: 4.0.6 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + optional: true + + base-x@5.0.1: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.11.9: {} + + big.js@6.2.2: {} + + blakejs@1.2.1: {} + + borsh@2.0.0: {} + + browserslist@4.28.7: + dependencies: + baseline-browser-mapping: 2.11.9 + caniuse-lite: 1.0.30001806 + electron-to-chromium: 1.5.399 + node-releases: 2.0.51 + update-browserslist-db: 1.2.3(browserslist@4.28.7) + + bs58@6.0.0: + dependencies: + base-x: 5.0.1 + + bs58check@4.0.0: + dependencies: + '@noble/hashes': 1.8.0 + bs58: 6.0.0 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + optional: true + + camelcase@5.3.1: {} + + caniuse-lite@1.0.30001806: {} + + cardinal@2.1.1: + dependencies: + ansicolors: 0.3.2 + redeyed: 2.1.1 + + cbor-extract@2.2.2: + dependencies: + node-gyp-build-optional-packages: 5.1.1 + optionalDependencies: + '@cbor-extract/cbor-extract-darwin-arm64': 2.2.2 + '@cbor-extract/cbor-extract-darwin-x64': 2.2.2 + '@cbor-extract/cbor-extract-linux-arm': 2.2.2 + '@cbor-extract/cbor-extract-linux-arm64': 2.2.2 + '@cbor-extract/cbor-extract-linux-x64': 2.2.2 + '@cbor-extract/cbor-extract-win32-x64': 2.2.2 + optional: true + + cbor-js@0.1.0: {} + + cbor-x@1.6.5: + optionalDependencies: + cbor-extract: 2.2.2 + + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + + chalk@5.6.2: + optional: true + + charenc@0.0.2: + optional: true + + check-error@2.1.3: {} + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clsx@1.2.1: + optional: true + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + optional: true + + commander@14.0.2: + optional: true + + convert-source-map@2.0.0: {} + + cookie-es@1.2.3: {} + + cross-fetch@3.2.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + crossws@0.3.5: + dependencies: + uncrypto: 0.1.3 + + crypt@0.0.2: + optional: true + + csstype@3.2.3: {} + + dayjs@1.11.13: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decamelize@1.2.0: {} + + deep-eql@5.0.2: {} + + default-browser-id@5.0.1: {} + + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + + define-lazy-prop@3.0.0: {} + + defu@6.1.7: {} + + delayed-stream@1.0.0: + optional: true + + destr@2.0.5: {} + + detect-browser@5.3.0: {} + + detect-libc@2.1.2: + optional: true + + dijkstrajs@1.0.3: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + optional: true + + electron-to-chromium@1.5.399: {} + + emoji-regex@8.0.0: {} + + encode-utf8@1.0.3: {} + + es-define-property@1.0.1: + optional: true + + es-errors@1.3.0: + optional: true + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + optional: true + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + optional: true + + es-toolkit@1.44.0: {} + + es-toolkit@1.45.1: {} + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + escalade@3.2.0: {} + + esprima@4.0.1: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + ethers@6.17.0: + dependencies: + '@adraffy/ens-normalize': 1.11.1 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 22.7.5 + aes-js: 4.0.0-beta.5 + tslib: 2.7.0 + ws: 8.21.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + eventemitter3@5.0.1: {} + + eventemitter3@5.0.4: {} + + events@3.3.0: {} + + expect-type@1.4.0: {} + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + follow-redirects@1.16.0: + optional: true + + form-data@4.0.6: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + optional: true + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: + optional: true + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + optional: true + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + optional: true + + get-starknet-core@4.0.0: + dependencies: + '@starknet-io/types-js': 0.7.10 + + gopd@1.2.0: + optional: true + + graceful-fs@4.2.11: {} + + h3@1.15.11: + dependencies: + cookie-es: 1.2.3 + crossws: 0.3.5 + defu: 6.1.7 + destr: 2.0.5 + iron-webcrypto: 1.2.1 + node-mock-http: 1.0.5 + radix3: 1.1.2 + ufo: 1.6.4 + uncrypto: 0.1.3 + + has-symbols@1.1.0: + optional: true + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + optional: true + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + optional: true + + hpke-js@1.8.0: + dependencies: + '@hpke/chacha20poly1305': 1.8.0 + '@hpke/common': 1.10.1 + '@hpke/core': 1.9.0 + '@hpke/dhkem-x25519': 1.8.0 + '@hpke/dhkem-x448': 1.8.0 + + idb-keyval@6.2.1: + optional: true + + idb-keyval@6.3.0: {} + + ieee754@1.2.1: {} + + iron-webcrypto@1.2.1: {} + + is-buffer@1.1.6: + optional: true + + is-docker@3.0.0: {} + + is-fullwidth-code-point@3.0.0: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-retry-allowed@2.2.0: + optional: true + + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + + isows@1.0.7(ws@8.21.0): + dependencies: + ws: 8.21.0 + + jose@6.2.6: + optional: true + + js-tokens@4.0.0: {} + + js-tokens@9.0.1: {} + + jsesc@3.1.0: {} + + json5@2.2.3: {} + + jsonfile@6.2.1: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + keyvaluestorage-interface@1.0.0: {} + + lit-element@4.2.2: + dependencies: + '@lit-labs/ssr-dom-shim': 1.6.0 + '@lit/reactive-element': 2.1.2 + lit-html: 3.3.3 + + lit-html@3.3.3: + dependencies: + '@types/trusted-types': 2.0.7 + + lit@3.3.0: + dependencies: + '@lit/reactive-element': 2.1.2 + lit-element: 4.2.2 + lit-html: 3.3.3 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lossless-json@4.3.1: {} + + loupe@3.2.1: {} + + lru-cache@11.5.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: + optional: true + + md5@2.3.0: + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + optional: true + + micro-packed@0.7.3: + dependencies: + '@scure/base': 1.2.6 + + micro-sol-signer@0.5.0: + dependencies: + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + micro-packed: 0.7.3 + + mime-db@1.52.0: + optional: true + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + optional: true + + mipd@0.0.7(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 + + ms@2.1.3: {} + + multiformats@9.9.0: {} + + nanoid@3.3.16: {} + + node-fetch-native@1.6.7: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-gyp-build-optional-packages@5.1.1: + dependencies: + detect-libc: 2.1.2 + optional: true + + node-mock-http@1.0.5: {} + + node-releases@2.0.51: {} + + normalize-path@3.0.0: {} + + ofetch@1.5.1: + dependencies: + destr: 2.0.5 + node-fetch-native: 1.6.7 + ufo: 1.6.4 + + on-exit-leak-free@2.1.2: {} + + open@10.2.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + + ox@0.14.33(typescript@5.9.3)(zod@3.22.4): + dependencies: + '@adraffy/ens-normalize': 1.11.1 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.2.3(typescript@5.9.3)(zod@3.22.4) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - zod + + ox@0.14.33(typescript@5.9.3)(zod@3.25.76): + dependencies: + '@adraffy/ens-normalize': 1.11.1 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.2.3(typescript@5.9.3)(zod@3.25.76) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - zod + + ox@0.4.4(typescript@5.9.3)(zod@3.25.76): + dependencies: + '@adraffy/ens-normalize': 1.11.1 + '@noble/curves': 1.7.0 + '@noble/hashes': 1.6.1 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.3.0(typescript@5.9.3)(zod@3.25.76) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - zod + + ox@0.6.9(typescript@5.9.3)(zod@3.25.76): + dependencies: + '@adraffy/ens-normalize': 1.11.1 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.3.0(typescript@5.9.3)(zod@3.25.76) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - zod + optional: true + + ox@0.9.3(typescript@5.9.3)(zod@3.25.76): + dependencies: + '@adraffy/ens-normalize': 1.11.1 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.3.0(typescript@5.9.3)(zod@3.25.76) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - zod + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-try@2.2.0: {} + + pako@2.2.0: {} + + path-exists@4.0.0: {} + + pathe@2.0.3: {} + + pathval@2.0.1: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.5: {} + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.1.0: {} + + pino@10.0.0: + dependencies: + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.1.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + slow-redact: 0.3.2 + sonic-boom: 4.2.1 + thread-stream: 3.2.0 + + playwright-core@1.62.1: {} + + playwright@1.62.1: + dependencies: + playwright-core: 1.62.1 + optionalDependencies: + fsevents: 2.3.2 + + pngjs@5.0.0: {} + + postcss@8.5.25: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + preact@10.24.2: + optional: true + + process-warning@5.1.0: {} + + proxy-compare@3.0.1: {} + + proxy-from-env@2.1.0: + optional: true + + pvtsutils@1.3.6: + dependencies: + tslib: 2.8.1 + + pvutils@1.1.5: {} + + qrcode@1.5.3: + dependencies: + dijkstrajs: 1.0.3 + encode-utf8: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + + quick-format-unescaped@4.0.4: {} + + radix3@1.1.2: {} + + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react-refresh@0.17.0: {} + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + readdirp@5.0.0: {} + + real-require@0.2.0: {} + + redeyed@2.1.1: + dependencies: + esprima: 4.0.1 + + reflect-metadata@0.2.2: {} + + require-directory@2.1.1: {} + + require-main-filename@2.0.0: {} + + rollup@4.62.3: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.3 + '@rollup/rollup-android-arm64': 4.62.3 + '@rollup/rollup-darwin-arm64': 4.62.3 + '@rollup/rollup-darwin-x64': 4.62.3 + '@rollup/rollup-freebsd-arm64': 4.62.3 + '@rollup/rollup-freebsd-x64': 4.62.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.3 + '@rollup/rollup-linux-arm-musleabihf': 4.62.3 + '@rollup/rollup-linux-arm64-gnu': 4.62.3 + '@rollup/rollup-linux-arm64-musl': 4.62.3 + '@rollup/rollup-linux-loong64-gnu': 4.62.3 + '@rollup/rollup-linux-loong64-musl': 4.62.3 + '@rollup/rollup-linux-ppc64-gnu': 4.62.3 + '@rollup/rollup-linux-ppc64-musl': 4.62.3 + '@rollup/rollup-linux-riscv64-gnu': 4.62.3 + '@rollup/rollup-linux-riscv64-musl': 4.62.3 + '@rollup/rollup-linux-s390x-gnu': 4.62.3 + '@rollup/rollup-linux-x64-gnu': 4.62.3 + '@rollup/rollup-linux-x64-musl': 4.62.3 + '@rollup/rollup-openbsd-x64': 4.62.3 + '@rollup/rollup-openharmony-arm64': 4.62.3 + '@rollup/rollup-win32-arm64-msvc': 4.62.3 + '@rollup/rollup-win32-ia32-msvc': 4.62.3 + '@rollup/rollup-win32-x64-gnu': 4.62.3 + '@rollup/rollup-win32-x64-msvc': 4.62.3 + fsevents: 2.3.3 + + run-applescript@7.1.0: {} + + safe-stable-stringify@2.5.0: {} + + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + + semver@6.3.1: {} + + semver@7.7.2: {} + + set-blocking@2.0.0: {} + + sha256-uint8array@0.10.7: {} + + siginfo@2.0.0: {} + + slow-redact@0.3.2: {} + + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + + source-map-js@1.2.1: {} + + split2@4.2.0: {} + + stackback@0.0.2: {} + + starknet@8.9.2: + dependencies: + '@noble/curves': 1.7.0 + '@noble/hashes': 1.6.1 + '@scure/base': 1.2.6 + '@scure/starknet': 1.1.0 + '@starknet-io/starknet-types-08': '@starknet-io/types-js@0.8.4' + '@starknet-io/starknet-types-09': '@starknet-io/types-js@0.9.2' + abi-wan-kanabi: 2.2.4 + lossless-json: 4.3.1 + pako: 2.2.0 + ts-mixer: 6.0.4 + + starknet@9.4.2(typescript@5.9.3)(zod@3.25.76): + dependencies: + '@noble/curves': 1.7.0 + '@noble/hashes': 1.6.1 + '@scure/base': 1.2.6 + '@scure/starknet': 1.1.0 + '@starknet-io/get-starknet-wallet-standard': 5.0.0(typescript@5.9.3)(zod@3.25.76) + '@starknet-io/starknet-types-010': '@starknet-io/types-js@0.10.0' + '@starknet-io/starknet-types-09': '@starknet-io/types-js@0.9.2' + abi-wan-kanabi: 2.2.4 + lossless-json: 4.3.1 + pako: 2.2.0 + ts-mixer: 6.0.4 + transitivePeerDependencies: + - typescript + - zod + + std-env@3.10.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + + thread-stream@3.2.0: + dependencies: + real-require: 0.2.0 + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + + tinyspy@4.0.4: {} + + tr46@0.0.3: {} + + ts-mixer@6.0.4: {} + + tslib@1.14.1: {} + + tslib@2.7.0: {} + + tslib@2.8.1: {} + + tsyringe@4.10.0: + dependencies: + tslib: 1.14.1 + + typescript@5.9.3: {} + + ufo@1.6.4: {} + + uint8arrays@3.1.1: + dependencies: + multiformats: 9.9.0 + + uncrypto@0.1.3: {} + + undici-types@6.19.8: {} + + undici-types@7.29.0: + optional: true + + universalify@2.0.1: {} + + unstorage@1.17.5(idb-keyval@6.3.0): + dependencies: + anymatch: 3.1.3 + chokidar: 5.0.0 + destr: 2.0.5 + h3: 1.15.11 + lru-cache: 11.5.2 + node-fetch-native: 1.6.7 + ofetch: 1.5.1 + ufo: 1.6.4 + optionalDependencies: + idb-keyval: 6.3.0 + + update-browserslist-db@1.2.3(browserslist@4.28.7): + dependencies: + browserslist: 4.28.7 + escalade: 3.2.0 + picocolors: 1.1.1 + + valtio@2.1.7(@types/react@18.3.31)(react@18.3.1): + dependencies: + proxy-compare: 3.0.1 + optionalDependencies: + '@types/react': 18.3.31 + react: 18.3.1 + + viem@2.55.10(typescript@5.9.3)(zod@3.22.4): + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.2.3(typescript@5.9.3)(zod@3.22.4) + isows: 1.0.7(ws@8.21.0) + ox: 0.14.33(typescript@5.9.3)(zod@3.22.4) + ws: 8.21.0 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + viem@2.55.10(typescript@5.9.3)(zod@3.25.76): + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.2.3(typescript@5.9.3)(zod@3.25.76) + isows: 1.0.7(ws@8.21.0) + ox: 0.14.33(typescript@5.9.3)(zod@3.25.76) + ws: 8.21.0 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + vite-node@3.2.4(@types/node@22.7.5): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 5.4.21(@types/node@22.7.5) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite@5.4.21(@types/node@22.7.5): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.25 + rollup: 4.62.3 + optionalDependencies: + '@types/node': 22.7.5 + fsevents: 2.3.3 + + vitest@3.2.7(@types/node@22.7.5): + dependencies: + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.7 + '@vitest/mocker': 3.2.7(vite@5.4.21(@types/node@22.7.5)) + '@vitest/pretty-format': 3.2.7 + '@vitest/runner': 3.2.7 + '@vitest/snapshot': 3.2.7 + '@vitest/spy': 3.2.7 + '@vitest/utils': 3.2.7 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.4.0 + magic-string: 0.30.21 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.17 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 5.4.21(@types/node@22.7.5) + vite-node: 3.2.4(@types/node@22.7.5) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.7.5 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-module@2.0.1: {} + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + ws@7.5.13: {} + + ws@8.21.0: {} + + ws@8.21.1: + optional: true + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.1 + + y18n@4.0.3: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + + yargs-parser@21.1.1: {} + + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + zod@3.22.4: {} + + zod@3.25.76: {} + + zustand@5.0.3(@types/react@18.3.31)(react@18.3.1): + optionalDependencies: + '@types/react': 18.3.31 + react: 18.3.1 + optional: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..a40b32c --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - sdk + - app diff --git a/scripts/gen-tables.mjs b/scripts/gen-tables.mjs new file mode 100644 index 0000000..cb66163 --- /dev/null +++ b/scripts/gen-tables.mjs @@ -0,0 +1,79 @@ +#!/usr/bin/env node +// Regenerates sdk/src/tables.ts from src/beast_definitions.cairo. +// +// The name tables are the one part of the SDK that genuinely duplicates +// contract data, so they are generated rather than transcribed: a hand-copied +// list of 75 species drifts silently, and a wrong species name is a wrong NFT. +// +// Tiers and types are NOT generated — they are formulas (see sdk/src/species.ts), +// and the SDK's tests pin them against the contract's own test anchors. + +import { readFileSync, writeFileSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = join(dirname(fileURLToPath(import.meta.url)), '..'); +const source = readFileSync(join(root, 'src/beast_definitions.cairo'), 'utf8'); + +/** + * Each table is an if/else chain of short-string literals in contract order, + * with a fallback literal at the end that is not a real entry. + */ +function extractTable(fnName, expected) { + const start = source.indexOf(`pub fn ${fnName}(`); + if (start === -1) throw new Error(`could not find ${fnName}`); + + // Run to the next top-level `pub fn`, or the end of the file. + const next = source.indexOf('\npub fn ', start + 1); + const body = source.slice(start, next === -1 ? undefined : next); + + const names = [...body.matchAll(/^\s*'([^']*)'/gm)].map((m) => m[1]); + const entries = names.slice(0, expected); + + if (entries.length !== expected) { + throw new Error(`${fnName}: expected ${expected} entries, found ${entries.length}`); + } + if (entries.some((n) => n.length === 0)) { + throw new Error(`${fnName}: found an empty entry — the parse is misaligned`); + } + return entries; +} + +const names = extractTable('get_beast_name', 75); +const prefixes = extractTable('get_prefix', 69); +const suffixes = extractTable('get_suffix', 18); + +const block = (arr, perLine = 5) => { + const lines = []; + for (let i = 0; i < arr.length; i += perLine) { + lines.push(' ' + arr.slice(i, i + perLine).map((x) => `'${x}',`).join(' ')); + } + return lines.join('\n'); +}; + +const output = `// GENERATED from src/beast_definitions.cairo — do not edit by hand. +// Regenerate with \`node scripts/gen-tables.mjs\` from the repo root. +// +// Index 0 of each array is species/affix 1: the contract numbers these from +// 1, and 0 means "absent" for affixes. + +/** The 75 genesis species, in contract order (index 0 === species 1). */ +export const GENESIS_SPECIES_NAMES: readonly string[] = [ +${block(names)} +] as const; + +/** Name prefixes 1-69. Shared by every species, genesis and community. */ +export const PREFIX_NAMES: readonly string[] = [ +${block(prefixes)} +] as const; + +/** Name suffixes 1-18. Shared by every species, genesis and community. */ +export const SUFFIX_NAMES: readonly string[] = [ +${block(suffixes)} +] as const; +`; + +writeFileSync(join(root, 'sdk/src/tables.ts'), output); +console.log( + `Wrote sdk/src/tables.ts: ${names.length} species, ${prefixes.length} prefixes, ${suffixes.length} suffixes`, +); diff --git a/sdk/.gitignore b/sdk/.gitignore new file mode 100644 index 0000000..1eae0cf --- /dev/null +++ b/sdk/.gitignore @@ -0,0 +1,2 @@ +dist/ +node_modules/ diff --git a/sdk/README.md b/sdk/README.md new file mode 100644 index 0000000..eb80940 --- /dev/null +++ b/sdk/README.md @@ -0,0 +1,92 @@ +# @provable-games/beasts-sdk + +TypeScript SDK for the Beasts onchain bestiary. + +```bash +pnpm add @provable-games/beasts-sdk starknet +``` + +## Everything static is offline + +A Beast's token ID *is* the Beast. The 116-bit layout encodes species, affixes, +level, health, tier, type, and the shiny/animated flags, so the full static +profile is recoverable without touching a node: + +```ts +import { decodeTokenId, beastPower, fullBeastName } from '@provable-games/beasts-sdk'; + +const beast = decodeTokenId('0x2e0064000a081000000000000004c'); +// { id: 76n, prefix: 1, suffix: 1, level: 10, health: 100, +// shiny: 0, animated: 1, tier: 3, beastType: 1 } + +beastPower(beast); // 30 — level * (6 - tier) +``` + +Only two things need a chain read, and both cache per species: the **name** and +the **art** of community species. Genesis species (1–75) resolve entirely +offline: + +```ts +import { genesisSpecies, fullBeastName, decodeTokenId } from '@provable-games/beasts-sdk'; + +genesisSpecies(1n); // { name: 'Warlock', tier: 1, beastType: 0 } +fullBeastName(decodeTokenId(genesisWarlockTokenId)); // 'Warlock' +fullBeastName(communityBeast, 'Gloomfang'); // '"Agony Bane" Gloomfang' +``` + +## Genesis Beasts are derived, not flagged + +There is no genesis bit. The `(id, 0, 0)` affix slot is reserved as each +species' Genesis Beast — the artist's provenance token — so `isGenesis` is just +`prefix === 0 && suffix === 0`. Every other mint requires both affixes, which is +what caps a species at exactly 1,243. + +## Validation mirrors the contract + +`validateSpeciesName`, `validateRenderableArt`, `validateFactoryArt` and +`validateArtSet` reproduce the contract's guards so a UI can fail fast instead +of failing a transaction. They are a convenience, never the security boundary — +the contract re-checks everything and is the only thing that decides what is +valid. + +The name charset is an injection guard, not a style rule: the contract's JSON +and SVG builders embed names unescaped. Names are deliberately **not** unique — +requiring uniqueness would let anyone squat the good ones. + +## Reads and calls + +`BeastsClient` returns `Call` objects rather than sending them, so the caller +decides how to sign — a wallet popup, a session, or a multicall batching several +changes into one transaction. + +```ts +import { BeastsClient, BeastType, SEPOLIA_ADDRESSES } from '@provable-games/beasts-sdk'; +import { RpcProvider } from 'starknet'; + +const client = new BeastsClient(new RpcProvider({ nodeUrl }), SEPOLIA_ADDRESSES, account); + +await client.execute( + client.registerWithArtCall({ + name: 'Gloomfang', + beastType: BeastType.Hunter, + tier: 3, + minter: dungeonAddress, // '0x0' registers paused + art: { pngRegular, pngShiny, gifRegular, gifShiny }, + }), +); +``` + +## Tests + +```bash +pnpm test # unit tests, no network +pnpm test:live # additionally reads the Sepolia deployment +``` + +The unit tests are anchored on two token IDs produced by the deployed contract, +not by this SDK, so a layout drift between Cairo and TypeScript fails the suite. +The live tests prove the client's calldata and ABI decoding match the deployed +contracts — something fixtures cannot. + +`src/tables.ts` is generated from `src/beast_definitions.cairo`; regenerate with +`node scripts/gen-tables.mjs` from the repo root rather than editing it. diff --git a/sdk/package.json b/sdk/package.json new file mode 100644 index 0000000..a7121d1 --- /dev/null +++ b/sdk/package.json @@ -0,0 +1,30 @@ +{ + "name": "@provable-games/beasts-sdk", + "version": "0.1.0", + "description": "TypeScript SDK for the Beasts onchain bestiary: token ID codec, species resolution, and the permissionless registry.", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "files": ["dist"], + "scripts": { + "build": "tsc -p tsconfig.build.json", + "typecheck": "tsc --noEmit", + "test": "vitest run", + "test:live": "RUN_LIVE_TESTS=1 vitest run" + }, + "peerDependencies": { + "starknet": "^9.0.0" + }, + "devDependencies": { + "starknet": "9.4.2", + "typescript": "^5.8.3", + "vitest": "^3.0.0" + }, + "license": "MIT" +} diff --git a/sdk/src/index.ts b/sdk/src/index.ts new file mode 100644 index 0000000..2e333b0 --- /dev/null +++ b/sdk/src/index.ts @@ -0,0 +1,52 @@ +export { + FIRST_COMMUNITY_ID, + GENESIS_SPECIES_MAX, + MAX_SUPPLY_PER_SPECIES, + TOKEN_ID_BITS, + TokenIdError, + beastPower, + decodeTokenId, + encodeTokenId, + genesisBeast, + isGenesis, + isGenesisSpecies, +} from './tokenId.js'; + +export { + fullBeastName, + genesisSpecies, + genesisSpeciesName, + genesisTier, + genesisType, + prefixName, + suffixName, +} from './species.js'; + +export { + ALLOWED_ART_PREFIXES, + MAX_NAME_BYTES, + type ValidationResult, + validateArtSet, + validateFactoryArt, + validateRenderableArt, + validateSpeciesName, + validateTier, +} from './validation.js'; + +export { + BeastsClient, + SEPOLIA_ADDRESSES, + type BeastsAddresses, + type RegisterParams, + type RegisterWithArtParams, +} from './registry.js'; + +export { GENESIS_SPECIES_NAMES, PREFIX_NAMES, SUFFIX_NAMES } from './tables.js'; + +export { + BEAST_TYPE_NAMES, + BeastType, + type ArtSet, + type Beast, + type BeastDefinition, +} from './types.js'; diff --git a/sdk/src/registry.ts b/sdk/src/registry.ts new file mode 100644 index 0000000..7c4a14b --- /dev/null +++ b/sdk/src/registry.ts @@ -0,0 +1,319 @@ +import type { AccountInterface, Call, ProviderInterface } from 'starknet'; +import { CallData, byteArray, shortString } from 'starknet'; +import { decodeTokenId } from './tokenId.js'; +import { BeastType, type ArtSet, type Beast, type BeastDefinition } from './types.js'; + +/** Addresses of a deployed Beasts stack. */ +export interface BeastsAddresses { + nft: string; + registry: string; +} + +/** Deployed stacks, from `docs/sepolia-v3-deployment.md`. */ +export const SEPOLIA_ADDRESSES: BeastsAddresses = { + nft: '0x01dac77837c6751777d917051a6e405967c5c75f46df5ab7c635e52819634bfd', + registry: '0x06d46c98087a1246182c6cd8ef144ee0a67da6e6cc9e44e39aef08cf92d30045', +}; + +export interface RegisterWithArtParams { + name: string; + beastType: BeastType; + tier: number; + /** Dungeon allowed to mint. Pass `'0x0'` to register in a paused state. */ + minter: string; + art: ArtSet; +} + +export interface RegisterParams { + name: string; + beastType: BeastType; + tier: number; + minter: string; + /** An `IBeastArtProvider` the artist controls. */ + artProvider: string; +} + +/** + * Reads and call-builders for the Beasts stack. + * + * Write methods return `Call` objects rather than executing them, so the + * caller decides how to sign — a wallet popup, a Cartridge session, or a + * multicall batching several changes into one transaction. Only + * `execute` actually sends, and only if an account was supplied. + */ +export class BeastsClient { + constructor( + private readonly provider: ProviderInterface, + private readonly addresses: BeastsAddresses = SEPOLIA_ADDRESSES, + private readonly account?: AccountInterface, + ) {} + + get nftAddress(): string { + return this.addresses.nft; + } + + get registryAddress(): string { + return this.addresses.registry; + } + + // ------------------------------------------------------------- reads + + /** Full definition of a registered community species. Reverts for 1-75. */ + async getDefinition(beastId: bigint): Promise { + const raw = (await this.provider.callContract({ + contractAddress: this.addresses.registry, + entrypoint: 'get_definition', + calldata: CallData.compile([beastId.toString()]), + })) as string[]; + + // BeastDefinition: name, type, tier, minter, artist, art_provider, + // stats_source, factory, art_locked, minter_locked + return { + name: shortString.decodeShortString(raw[0]), + beastType: Number(BigInt(raw[1])) as BeastType, + tier: Number(BigInt(raw[2])), + minter: toHex(raw[3]), + artist: toHex(raw[4]), + artProvider: toHex(raw[5]), + statsSource: toHex(raw[6]), + factoryProvider: BigInt(raw[7]) === 1n, + artLocked: BigInt(raw[8]) === 1n, + minterLocked: BigInt(raw[9]) === 1n, + }; + } + + /** Total species, genesis included. `next_id - 1`. */ + async speciesCount(): Promise { + const [raw] = (await this.provider.callContract({ + contractAddress: this.addresses.registry, + entrypoint: 'species_count', + calldata: [], + })) as string[]; + return BigInt(raw); + } + + async isRegistered(beastId: bigint): Promise { + const [raw] = (await this.provider.callContract({ + contractAddress: this.addresses.registry, + entrypoint: 'is_registered', + calldata: CallData.compile([beastId.toString()]), + })) as string[]; + return BigInt(raw) === 1n; + } + + /** Minted NFT count. Not the highest token ID — IDs are not sequential. */ + async totalSupply(): Promise { + const raw = (await this.provider.callContract({ + contractAddress: this.addresses.nft, + entrypoint: 'total_supply', + calldata: [], + })) as string[]; + return u256FromParts(raw[0], raw[1]); + } + + /** Decodes a token's Beast. Local decode; no chain read is needed. */ + decodeBeast(tokenId: bigint | string): Beast { + return decodeTokenId(tokenId); + } + + async ownerOf(tokenId: bigint): Promise { + const [raw] = (await this.provider.callContract({ + contractAddress: this.addresses.nft, + entrypoint: 'owner_of', + calldata: CallData.compile(u256ToParts(tokenId)), + })) as string[]; + return toHex(raw); + } + + /** Rank within the species, by power then health. Genesis Beasts are 0. */ + async getBeastRank(tokenId: bigint): Promise { + const [raw] = (await this.provider.callContract({ + contractAddress: this.addresses.nft, + entrypoint: 'get_beast_rank', + calldata: CallData.compile(u256ToParts(tokenId)), + })) as string[]; + return Number(BigInt(raw)); + } + + /** The contract's own metadata for a token: a base64 JSON data URI. */ + async tokenUri(tokenId: bigint): Promise { + const raw = (await this.provider.callContract({ + contractAddress: this.addresses.nft, + entrypoint: 'token_uri', + calldata: CallData.compile(u256ToParts(tokenId)), + })) as string[]; + return byteArray.stringFromByteArray(decodeByteArray(raw)); + } + + /** Art for a Beast, straight from its species' provider. */ + async getArt(beast: Beast): Promise { + const definition = await this.getDefinition(beast.id); + const raw = (await this.provider.callContract({ + contractAddress: definition.artProvider, + entrypoint: 'get_data_uri', + calldata: CallData.compile([ + beast.id.toString(), + beast.prefix, + beast.suffix, + beast.level, + beast.health, + beast.shiny, + beast.animated, + beast.tier, + beast.beastType, + ]), + })) as string[]; + return byteArray.stringFromByteArray(decodeByteArray(raw)); + } + + // ------------------------------------------------------ call builders + + /** + * The simple path: the registry deploys a canonical `StoredArtProvider` + * holding the four variants. One transaction, no contract knowledge needed, + * and the artist's Genesis Beast lands in the same transaction. + */ + registerWithArtCall(params: RegisterWithArtParams): Call { + return { + contractAddress: this.addresses.registry, + entrypoint: 'register_beast_with_art', + calldata: CallData.compile([ + shortString.encodeShortString(params.name), + params.beastType, + params.tier, + params.minter, + byteArray.byteArrayFromString(params.art.pngRegular), + byteArray.byteArrayFromString(params.art.pngShiny), + byteArray.byteArrayFromString(params.art.gifRegular), + byteArray.byteArrayFromString(params.art.gifShiny), + ]), + }; + } + + /** The advanced path: the artist supplies their own `IBeastArtProvider`. */ + registerCall(params: RegisterParams): Call { + return { + contractAddress: this.addresses.registry, + entrypoint: 'register_beast', + calldata: CallData.compile([ + shortString.encodeShortString(params.name), + params.beastType, + params.tier, + params.minter, + params.artProvider, + ]), + }; + } + + updateArtCall(beastId: bigint, art: ArtSet): Call { + return { + contractAddress: this.addresses.registry, + entrypoint: 'update_art', + calldata: CallData.compile([ + beastId.toString(), + byteArray.byteArrayFromString(art.pngRegular), + byteArray.byteArrayFromString(art.pngShiny), + byteArray.byteArrayFromString(art.gifRegular), + byteArray.byteArrayFromString(art.gifShiny), + ]), + }; + } + + /** Zero pauses the species — mints revert until a minter is set again. */ + setMinterCall(beastId: bigint, minter: string): Call { + return this.registryCall('set_minter', [beastId.toString(), minter]); + } + + /** One-way. After this the minter can never change. */ + lockMinterCall(beastId: bigint): Call { + return this.registryCall('lock_minter', [beastId.toString()]); + } + + /** + * One-way. Freezes the art *pointer*. For a factory provider that is a true + * freeze, since its only mutator is registry-gated. For a custom provider it + * freezes only the address — the provider may still change what it returns, + * which is why `notify_art_updated` stays open for those. + */ + lockArtCall(beastId: bigint): Call { + return this.registryCall('lock_art', [beastId.toString()]); + } + + setArtProviderCall(beastId: bigint, provider: string): Call { + return this.registryCall('set_art_provider', [beastId.toString(), provider]); + } + + /** Re-announces art to marketplaces after a custom provider changed. */ + notifyArtUpdatedCall(beastId: bigint): Call { + return this.registryCall('notify_art_updated', [beastId.toString()]); + } + + /** Zero clears the source, turning kill stats off for the species. */ + setStatsSourceCall(beastId: bigint, source: string): Call { + return this.registryCall('set_stats_source', [beastId.toString(), source]); + } + + transferArtistRoleCall(beastId: bigint, newArtist: string): Call { + return this.registryCall('transfer_artist_role', [beastId.toString(), newArtist]); + } + + /** Permissionless: pulls a community token's stats into the render cache. */ + refreshStatsCall(tokenId: bigint): Call { + return { + contractAddress: this.addresses.nft, + entrypoint: 'refresh_stats', + calldata: CallData.compile(u256ToParts(tokenId)), + }; + } + + // ----------------------------------------------------------- execute + + /** Sends one or more calls. Requires an account. */ + async execute(calls: Call | Call[]): Promise { + if (!this.account) { + throw new Error('BeastsClient was constructed without an account; cannot execute'); + } + const { transaction_hash } = await this.account.execute(calls); + return transaction_hash; + } + + private registryCall(entrypoint: string, args: unknown[]): Call { + return { + contractAddress: this.addresses.registry, + entrypoint, + calldata: CallData.compile(args as never), + }; + } +} + +// ------------------------------------------------------------- helpers + +function toHex(value: string): string { + return `0x${BigInt(value).toString(16).padStart(64, '0')}`; +} + +function u256ToParts(value: bigint): [string, string] { + const MASK = (1n << 128n) - 1n; + return [(value & MASK).toString(), (value >> 128n).toString()]; +} + +function u256FromParts(low: string, high: string): bigint { + return BigInt(low) + (BigInt(high) << 128n); +} + +/** + * A ByteArray on the wire is `[num_full_words, ...words, pending_word, + * pending_len]`. starknet.js wants that shape as an object. + */ +function decodeByteArray(raw: string[]): { + data: string[]; + pending_word: string; + pending_word_len: number; +} { + const wordCount = Number(BigInt(raw[0])); + return { + data: raw.slice(1, 1 + wordCount), + pending_word: raw[1 + wordCount], + pending_word_len: Number(BigInt(raw[2 + wordCount])), + }; +} diff --git a/sdk/src/species.ts b/sdk/src/species.ts new file mode 100644 index 0000000..416624a --- /dev/null +++ b/sdk/src/species.ts @@ -0,0 +1,75 @@ +import { GENESIS_SPECIES_NAMES, PREFIX_NAMES, SUFFIX_NAMES } from './tables.js'; +import { GENESIS_SPECIES_MAX, isGenesisSpecies } from './tokenId.js'; +import { BeastType, type Beast } from './types.js'; + +/** + * Tier of a genesis species. + * + * The contract expresses this as ranges, but they are a formula: species are + * laid out in three blocks of 25 (one per type), and each block runs T1..T5 in + * groups of five. + */ +export function genesisTier(id: bigint): number { + assertGenesisSpecies(id); + return Math.floor((Number(id - 1n) % 25) / 5) + 1; +} + +/** Type of a genesis species: 1-25 Magic, 26-50 Hunter, 51-75 Brute. */ +export function genesisType(id: bigint): BeastType { + assertGenesisSpecies(id); + return Math.floor(Number(id - 1n) / 25) as BeastType; +} + +/** Display name of a genesis species. */ +export function genesisSpeciesName(id: bigint): string { + assertGenesisSpecies(id); + return GENESIS_SPECIES_NAMES[Number(id) - 1]; +} + +/** Prefix display name, or `null` for the Genesis Beast's absent affix. */ +export function prefixName(prefix: number): string | null { + if (prefix === 0) return null; + if (prefix < 0 || prefix > PREFIX_NAMES.length) { + throw new RangeError(`prefix out of range: ${prefix}`); + } + return PREFIX_NAMES[prefix - 1]; +} + +/** Suffix display name, or `null` for the Genesis Beast's absent affix. */ +export function suffixName(suffix: number): string | null { + if (suffix === 0) return null; + if (suffix < 0 || suffix > SUFFIX_NAMES.length) { + throw new RangeError(`suffix out of range: ${suffix}`); + } + return SUFFIX_NAMES[suffix - 1]; +} + +/** + * Full display name, matching the contract's metadata exactly. + * + * A Genesis Beast is just the species name; every other Beast is + * `"Prefix Suffix" Species`. Community species must supply `speciesName` — + * only the registry knows it. + */ +export function fullBeastName(beast: Beast, speciesName?: string): string { + const base = speciesName ?? genesisSpeciesName(beast.id); + if (beast.prefix === 0) return base; + return `"${prefixName(beast.prefix)} ${suffixName(beast.suffix)}" ${base}`; +} + +/** + * Static traits of a genesis species, resolved offline. Community species get + * theirs from the registry — see `BeastRegistryClient.getDefinition`. + */ +export function genesisSpecies(id: bigint): { name: string; tier: number; beastType: BeastType } { + return { name: genesisSpeciesName(id), tier: genesisTier(id), beastType: genesisType(id) }; +} + +function assertGenesisSpecies(id: bigint): void { + if (!isGenesisSpecies(id)) { + throw new RangeError( + `species ${id} is not a genesis species (1-${GENESIS_SPECIES_MAX}); ` + + 'community species resolve through the registry', + ); + } +} diff --git a/sdk/src/tables.ts b/sdk/src/tables.ts new file mode 100644 index 0000000..2487985 --- /dev/null +++ b/sdk/src/tables.ts @@ -0,0 +1,50 @@ +// GENERATED from src/beast_definitions.cairo — do not edit by hand. +// Regenerate with `node scripts/gen-tables.mjs` from the repo root. +// +// Index 0 of each array is species/affix 1: the contract numbers these from +// 1, and 0 means "absent" for affixes. + +/** The 75 genesis species, in contract order (index 0 === species 1). */ +export const GENESIS_SPECIES_NAMES: readonly string[] = [ + 'Warlock', 'Typhon', 'Jiangshi', 'Anansi', 'Basilisk', + 'Gorgon', 'Kitsune', 'Lich', 'Chimera', 'Wendigo', + 'Rakshasa', 'Werewolf', 'Banshee', 'Draugr', 'Vampire', + 'Goblin', 'Ghoul', 'Wraith', 'Sprite', 'Kappa', + 'Fairy', 'Leprechaun', 'Kelpie', 'Pixie', 'Gnome', + 'Griffin', 'Manticore', 'Phoenix', 'Dragon', 'Minotaur', + 'Qilin', 'Ammit', 'Nue', 'Skinwalker', 'Chupacabra', + 'Weretiger', 'Wyvern', 'Roc', 'Harpy', 'Pegasus', + 'Hippogriff', 'Fenrir', 'Jaguar', 'Satori', 'Direwolf', + 'Bear', 'Wolf', 'Mantis', 'Spider', 'Rat', + 'Kraken', 'Colossus', 'Balrog', 'Leviathan', 'Tarrasque', + 'Titan', 'Nephilim', 'Behemoth', 'Hydra', 'Juggernaut', + 'Oni', 'Jotunn', 'Ettin', 'Cyclops', 'Giant', + 'Nemean Lion', 'Berserker', 'Yeti', 'Golem', 'Ent', + 'Troll', 'Bigfoot', 'Ogre', 'Orc', 'Skeleton', +] as const; + +/** Name prefixes 1-69. Shared by every species, genesis and community. */ +export const PREFIX_NAMES: readonly string[] = [ + 'Agony', 'Apocalypse', 'Armageddon', 'Beast', 'Behemoth', + 'Blight', 'Blood', 'Bramble', 'Brimstone', 'Brood', + 'Carrion', 'Cataclysm', 'Chimeric', 'Corpse', 'Corruption', + 'Damnation', 'Death', 'Demon', 'Dire', 'Dragon', + 'Dread', 'Doom', 'Dusk', 'Eagle', 'Empyrean', + 'Fate', 'Foe', 'Gale', 'Ghoul', 'Gloom', + 'Glyph', 'Golem', 'Grim', 'Hate', 'Havoc', + 'Honour', 'Horror', 'Hypnotic', 'Kraken', 'Loath', + 'Maelstrom', 'Mind', 'Miracle', 'Morbid', 'Oblivion', + 'Onslaught', 'Pain', 'Pandemonium', 'Phoenix', 'Plague', + 'Rage', 'Rapture', 'Rune', 'Skull', 'Sol', + 'Soul', 'Sorrow', 'Spirit', 'Storm', 'Tempest', + 'Torment', 'Vengeance', 'Victory', 'Viper', 'Vortex', + 'Woe', 'Wrath', 'Lights', 'Shimmering', +] as const; + +/** Name suffixes 1-18. Shared by every species, genesis and community. */ +export const SUFFIX_NAMES: readonly string[] = [ + 'Bane', 'Root', 'Bite', 'Song', 'Roar', + 'Grasp', 'Instrument', 'Glow', 'Bender', 'Shadow', + 'Whisper', 'Shout', 'Growl', 'Tear', 'Peak', + 'Form', 'Sun', 'Moon', +] as const; diff --git a/sdk/src/tokenId.ts b/sdk/src/tokenId.ts new file mode 100644 index 0000000..1dc8d0e --- /dev/null +++ b/sdk/src/tokenId.ts @@ -0,0 +1,185 @@ +import { BeastType, type Beast } from './types.js'; + +/** + * The 116-bit token ID layout, mirroring `pack_to_u256` in `src/pack.cairo`. + * + * ``` + * bits 0- 63 id (u64) + * bits 64- 70 prefix (7) + * bits 71- 75 suffix (5) + * bits 76- 91 level (16) + * bits 92-107 health (16) + * bit 108 shiny (1) + * bit 109 animated (1) + * bits 110-112 tier (3) + * bits 113-115 type (3) + * ``` + * + * Token IDs are deterministic, not sequential: the ID *is* the Beast. Every + * static trait is recoverable offline, so a client needs chain reads only for + * the species name and art of community species. + */ +const SHIFT = { + id: 0n, + prefix: 64n, + suffix: 71n, + level: 76n, + health: 92n, + shiny: 108n, + animated: 109n, + tier: 110n, + beastType: 113n, +} as const; + +const WIDTH = { + id: 64n, + prefix: 7n, + suffix: 5n, + level: 16n, + health: 16n, + shiny: 1n, + animated: 1n, + tier: 3n, + beastType: 3n, +} as const; + +const mask = (bits: bigint) => (1n << bits) - 1n; + +/** Total width of the layout. Anything above this bit must be zero. */ +export const TOKEN_ID_BITS = 116n; + +/** Highest species ID backed by the baked-in genesis tables. */ +export const GENESIS_SPECIES_MAX = 75n; + +/** First species ID the registry will assign. */ +export const FIRST_COMMUNITY_ID = 76n; + +/** Max mintable Beasts per species: 69 x 18 named variants + 1 Genesis. */ +export const MAX_SUPPLY_PER_SPECIES = 69 * 18 + 1; + +export class TokenIdError extends Error { + constructor(message: string) { + super(message); + this.name = 'TokenIdError'; + } +} + +/** + * Encodes a Beast into its canonical token ID. + * + * Validates the same ranges the contract does, so an ID produced here can + * never decode into a different Beast than the one passed in. + */ +export function encodeTokenId(beast: Beast): bigint { + assertEncodable(beast); + + return ( + (beast.id << SHIFT.id) | + (BigInt(beast.prefix) << SHIFT.prefix) | + (BigInt(beast.suffix) << SHIFT.suffix) | + (BigInt(beast.level) << SHIFT.level) | + (BigInt(beast.health) << SHIFT.health) | + (BigInt(beast.shiny) << SHIFT.shiny) | + (BigInt(beast.animated) << SHIFT.animated) | + (BigInt(beast.tier) << SHIFT.tier) | + (BigInt(beast.beastType) << SHIFT.beastType) + ); +} + +/** + * Decodes a token ID into its Beast. + * + * Applies the contract's `decode_token_id` checks: no residual high bits, a + * non-zero species, in-range tier/type/affixes, and the affix-pair rule that + * `(prefix === 0) === (suffix === 0)` — the `(id, 0, 0)` slot is reserved for + * the species' Genesis Beast and no other combination may be half-set. + */ +export function decodeTokenId(tokenId: bigint | string | number): Beast { + const packed = BigInt(tokenId); + + if (packed < 0n) throw new TokenIdError('token ID must be non-negative'); + if (packed >> TOKEN_ID_BITS) throw new TokenIdError('token ID has residual high bits'); + + const field = (key: keyof typeof SHIFT) => (packed >> SHIFT[key]) & mask(WIDTH[key]); + + const id = field('id'); + if (id === 0n) throw new TokenIdError('species ID must not be zero'); + + const prefix = Number(field('prefix')); + const suffix = Number(field('suffix')); + const tier = Number(field('tier')); + const beastType = Number(field('beastType')); + + if (tier < 1 || tier > 5) throw new TokenIdError(`tier out of range: ${tier}`); + if (beastType > 2) throw new TokenIdError(`beast type out of range: ${beastType}`); + if (prefix > 69) throw new TokenIdError(`prefix out of range: ${prefix}`); + if (suffix > 18) throw new TokenIdError(`suffix out of range: ${suffix}`); + if ((prefix === 0) !== (suffix === 0)) { + throw new TokenIdError('invalid affix combo: prefix and suffix must both be zero, or neither'); + } + + return { + id, + prefix, + suffix, + level: Number(field('level')), + health: Number(field('health')), + shiny: Number(field('shiny')) as 0 | 1, + animated: Number(field('animated')) as 0 | 1, + tier, + beastType: beastType as BeastType, + }; +} + +/** + * A Genesis Beast is derived, never stored: it is the one Beast per species + * holding the reserved `(id, 0, 0)` affix slot. It is the artist's provenance + * token for community species, and belongs to the collection owner for the + * original 75. + */ +export function isGenesis(beast: Beast): boolean { + return beast.prefix === 0 && beast.suffix === 0; +} + +/** True for the 75 species baked into the contract's tables. */ +export function isGenesisSpecies(id: bigint): boolean { + return id >= 1n && id <= GENESIS_SPECIES_MAX; +} + +/** Combat power, exactly as the contract computes it: `level * (6 - tier)`. */ +export function beastPower(beast: Beast): number { + const power = beast.level * (6 - beast.tier); + return power > 65535 ? 65535 : power; +} + +/** Builds the Genesis Beast of a species from its static traits. */ +export function genesisBeast(id: bigint, tier: number, beastType: BeastType): Beast { + return { id, prefix: 0, suffix: 0, level: 1, health: 100, shiny: 1, animated: 1, tier, beastType }; +} + +function assertEncodable(beast: Beast): void { + const inRange = (name: string, value: number | bigint, max: bigint) => { + const v = BigInt(value); + if (v < 0n || v > max) throw new TokenIdError(`${name} out of range: ${value}`); + }; + + if (beast.id <= 0n) throw new TokenIdError('species ID must be positive'); + inRange('id', beast.id, mask(WIDTH.id)); + inRange('level', beast.level, mask(WIDTH.level)); + inRange('health', beast.health, mask(WIDTH.health)); + + if (beast.prefix > 69) throw new TokenIdError(`prefix out of range: ${beast.prefix}`); + if (beast.suffix > 18) throw new TokenIdError(`suffix out of range: ${beast.suffix}`); + if (beast.prefix < 0 || beast.suffix < 0) throw new TokenIdError('affixes must be non-negative'); + if ((beast.prefix === 0) !== (beast.suffix === 0)) { + throw new TokenIdError('invalid affix combo: prefix and suffix must both be zero, or neither'); + } + if (beast.tier < 1 || beast.tier > 5) throw new TokenIdError(`tier out of range: ${beast.tier}`); + if (beast.beastType < 0 || beast.beastType > 2) { + throw new TokenIdError(`beast type out of range: ${beast.beastType}`); + } + if (beast.shiny !== 0 && beast.shiny !== 1) throw new TokenIdError('shiny must be 0 or 1'); + if (beast.animated !== 0 && beast.animated !== 1) { + throw new TokenIdError('animated must be 0 or 1'); + } +} diff --git a/sdk/src/types.ts b/sdk/src/types.ts new file mode 100644 index 0000000..38385da --- /dev/null +++ b/sdk/src/types.ts @@ -0,0 +1,59 @@ +/** Beast type codes exactly as encoded in the token ID. */ +export enum BeastType { + Magic = 0, + Hunter = 1, + Brute = 2, +} + +export const BEAST_TYPE_NAMES: Record = { + [BeastType.Magic]: 'Magic', + [BeastType.Hunter]: 'Hunter', + [BeastType.Brute]: 'Brute', +}; + +/** + * Everything a token ID encodes. This is the whole static profile of a Beast — + * no chain read is needed to produce it, which is the point of the 116-bit + * layout. + */ +export interface Beast { + /** Species ID. 1-75 are genesis species; 76+ are community species. */ + id: bigint; + /** 0-69. Zero only on a Genesis Beast. */ + prefix: number; + /** 0-18. Zero only on a Genesis Beast. */ + suffix: number; + level: number; + health: number; + shiny: 0 | 1; + animated: 0 | 1; + /** 1-5. */ + tier: number; + beastType: BeastType; +} + +/** A registered community species, as returned by `get_definition`. */ +export interface BeastDefinition { + name: string; + beastType: BeastType; + tier: number; + /** Dungeon allowed to mint this species. Zero means paused. */ + minter: string; + /** Registrant; holds the per-species admin role. */ + artist: string; + artProvider: string; + /** Zero means kill stats are off for this species. */ + statsSource: string; + /** True when `artProvider` is the registry's canonical factory deploy. */ + factoryProvider: boolean; + artLocked: boolean; + minterLocked: boolean; +} + +/** The four art variants a factory-provider species stores. */ +export interface ArtSet { + pngRegular: string; + pngShiny: string; + gifRegular: string; + gifShiny: string; +} diff --git a/sdk/src/validation.ts b/sdk/src/validation.ts new file mode 100644 index 0000000..650d014 --- /dev/null +++ b/sdk/src/validation.ts @@ -0,0 +1,151 @@ +/** + * Client-side mirrors of the contract's guards. + * + * These exist so the web app can reject bad input before it costs a + * transaction — they are a convenience, never the security boundary. The + * contract re-checks everything, and it is the only thing that decides what + * is valid. + */ + +// ---------------------------------------------------------------- names + +/** + * Species name charset, mirroring `assert_valid_name` in + * `src/beast_registry.cairo`. + * + * This is an injection guard, not a style rule: the contract's JSON and SVG + * builders embed names unescaped, so the charset is what keeps every token's + * metadata well-formed. Uniqueness is deliberately NOT enforced — requiring + * it would let anyone squat the good names. Species ID is the identity. + */ +const NAME_CHARSET = /^[A-Za-z0-9 '-]+$/; + +/** Names are stored in a single felt252, which holds at most 31 bytes. */ +export const MAX_NAME_BYTES = 31; + +export interface ValidationResult { + valid: boolean; + error?: string; +} + +export function validateSpeciesName(name: string): ValidationResult { + if (name.length === 0) return { valid: false, error: 'Name cannot be empty' }; + if (new TextEncoder().encode(name).length > MAX_NAME_BYTES) { + return { valid: false, error: `Name cannot exceed ${MAX_NAME_BYTES} bytes` }; + } + if (!NAME_CHARSET.test(name)) { + return { + valid: false, + error: "Name may only contain letters, numbers, spaces, apostrophes, and hyphens", + }; + } + if (name.startsWith(' ')) return { valid: false, error: 'Name cannot start with a space' }; + if (name.endsWith(' ')) return { valid: false, error: 'Name cannot end with a space' }; + return { valid: true }; +} + +// ------------------------------------------------------------------ art + +/** + * Media types the contract accepts from a community art provider at render + * time (`src/art_validation.cairo`). + */ +export const ALLOWED_ART_PREFIXES = [ + 'data:image/png;base64,', + 'data:image/gif;base64,', + 'data:image/webp;base64,', + 'data:image/svg+xml;base64,', +] as const; + +/** + * Base64-encoded magic bytes the *factory* provider additionally requires at + * write time (`src/stored_art_provider.cairo`). A fixed leading signature + * always encodes to a fixed character prefix, so this needs no decoding: + * PNG 89 50 4E 47 0D 0A 1A 0A + IHDR length -> "iVBORw0KGgo" + * GIF "GIF87a" -> "R0lGODdh", "GIF89a" -> "R0lGODlh" + */ +const PNG_MAGIC = 'iVBORw0KGgo'; +const GIF_MAGICS = ['R0lGODdh', 'R0lGODlh'] as const; + +const BASE64_BODY = /^[A-Za-z0-9+/]*={0,2}$/; + +/** + * Validates a data URI the way `token_uri` will when it renders: allowlisted + * media type plus a structurally sound standard-base64 payload. + * + * Deliberately imposes no size cap. If an artist is willing to pay for the + * storage and the network accepts the transaction, the art is valid. + */ +export function validateRenderableArt(uri: string): ValidationResult { + const prefix = ALLOWED_ART_PREFIXES.find((p) => uri.startsWith(p)); + if (!prefix) { + return { + valid: false, + error: 'Art must be a base64 data URI of type png, gif, webp, or svg+xml', + }; + } + + const payload = uri.slice(prefix.length); + if (payload.length === 0) return { valid: false, error: 'Art payload is empty' }; + if (payload.length % 4 !== 0) { + return { valid: false, error: 'Art payload is not valid base64 (length must be a multiple of 4)' }; + } + if (!BASE64_BODY.test(payload)) { + return { valid: false, error: 'Art payload contains characters outside the base64 alphabet' }; + } + return { valid: true }; +} + +/** + * Validates art destined for the *factory* provider, which is stricter than + * render-time: it must additionally carry real PNG or GIF magic bytes. This + * is what earns factory art its "verified" designation — a locked factory + * species is provably frozen and provably an inert image. + */ +export function validateFactoryArt(uri: string, kind: 'png' | 'gif'): ValidationResult { + const expectedPrefix = kind === 'png' ? 'data:image/png;base64,' : 'data:image/gif;base64,'; + if (!uri.startsWith(expectedPrefix)) { + return { valid: false, error: `Expected a ${kind.toUpperCase()} data URI` }; + } + + const structural = validateRenderableArt(uri); + if (!structural.valid) return structural; + + const payload = uri.slice(expectedPrefix.length); + if (kind === 'png') { + if (!payload.startsWith(PNG_MAGIC)) { + return { valid: false, error: 'File is not a valid PNG' }; + } + } else if (!GIF_MAGICS.some((m) => payload.startsWith(m))) { + return { valid: false, error: 'File is not a valid GIF (must be GIF87a or GIF89a)' }; + } + return { valid: true }; +} + +/** Validates the complete four-variant set the factory path requires. */ +export function validateArtSet(art: { + pngRegular: string; + pngShiny: string; + gifRegular: string; + gifShiny: string; +}): ValidationResult { + const checks: Array<[string, ValidationResult]> = [ + ['Regular PNG', validateFactoryArt(art.pngRegular, 'png')], + ['Shiny PNG', validateFactoryArt(art.pngShiny, 'png')], + ['Regular GIF', validateFactoryArt(art.gifRegular, 'gif')], + ['Shiny GIF', validateFactoryArt(art.gifShiny, 'gif')], + ]; + for (const [label, result] of checks) { + if (!result.valid) return { valid: false, error: `${label}: ${result.error}` }; + } + return { valid: true }; +} + +// ----------------------------------------------------------------- tier + +export function validateTier(tier: number): ValidationResult { + if (!Number.isInteger(tier) || tier < 1 || tier > 5) { + return { valid: false, error: 'Tier must be a whole number from 1 to 5' }; + } + return { valid: true }; +} diff --git a/sdk/test/live.test.ts b/sdk/test/live.test.ts new file mode 100644 index 0000000..ba03e74 --- /dev/null +++ b/sdk/test/live.test.ts @@ -0,0 +1,80 @@ +import { RpcProvider } from 'starknet'; +import { describe, expect, it } from 'vitest'; +import { BeastType, BeastsClient, SEPOLIA_ADDRESSES, decodeTokenId } from '../src/index.js'; + +/** + * Live reads against the Sepolia deployment in + * `docs/sepolia-v3-deployment.md`. + * + * Skipped by default — they need network and will drift if that deployment is + * replaced. Run with `pnpm test:live`. Their job is to prove the client's + * calldata and return-value decoding actually match the deployed ABI, which + * unit tests with hand-written fixtures cannot. + */ +const RPC_URL = process.env.STARKNET_RPC_URL ?? 'https://api.zan.top/public/starknet-sepolia/rpc/v0_10'; +const live = process.env.RUN_LIVE_TESTS ? describe : describe.skip; + +const GENESIS_WARLOCK = 0x7006400010000000000000000001n; +const GLOOMFANG = 0x2e0064000a081000000000000004cn; + +live('Sepolia deployment', () => { + const client = new BeastsClient(new RpcProvider({ nodeUrl: RPC_URL }), SEPOLIA_ADDRESSES); + + it('reads the registered community species', async () => { + const definition = await client.getDefinition(76n); + expect(definition.name).toBe('Gloomfang'); + expect(definition.beastType).toBe(BeastType.Hunter); + expect(definition.tier).toBe(3); + expect(definition.factoryProvider).toBe(true); + expect(definition.artLocked).toBe(false); + expect(definition.minterLocked).toBe(false); + // No stats source was set, so kill stats are off for this species. + expect(BigInt(definition.statsSource)).toBe(0n); + }, 30_000); + + it('counts species and supply', async () => { + expect(await client.speciesCount()).toBeGreaterThanOrEqual(76n); + expect(await client.totalSupply()).toBeGreaterThanOrEqual(76n); + }, 30_000); + + it('reports registration only above the genesis range', async () => { + expect(await client.isRegistered(76n)).toBe(true); + expect(await client.isRegistered(1n)).toBe(false); + expect(await client.isRegistered(9_999n)).toBe(false); + }, 30_000); + + it('ranks the community mint first in its species', async () => { + expect(await client.getBeastRank(GLOOMFANG)).toBe(1); + // Genesis Beasts sit outside the ranked list. + expect(await client.getBeastRank(GENESIS_WARLOCK)).toBe(0); + }, 30_000); + + it('renders token_uri as base64 JSON with the expected identity', async () => { + const uri = await client.tokenUri(GLOOMFANG); + expect(uri.startsWith('data:application/json;base64,')).toBe(true); + + const json = JSON.parse( + Buffer.from(uri.slice('data:application/json;base64,'.length), 'base64').toString('utf8'), + ); + expect(json.name).toBe('"Agony Bane" Gloomfang'); + + const attribute = (t: string) => + json.attributes.find((a: { trait_type: string }) => a.trait_type === t)?.value; + expect(attribute('Beast')).toBe('Gloomfang'); + expect(attribute('Type')).toBe('Hunter'); + expect(attribute('Tier')).toBe('3'); + expect(attribute('Power')).toBe('30'); + expect(attribute('Genesis')).toBe('0'); + }, 60_000); + + it('fetches art from the species art provider', async () => { + const art = await client.getArt(decodeTokenId(GLOOMFANG)); + // animated = 1, shiny = 0, so the provider must return the regular GIF. + expect(art.startsWith('data:image/gif;base64,R0lGOD')).toBe(true); + }, 30_000); + + it('agrees with the chain on who owns the genesis token', async () => { + const owner = await client.ownerOf(GENESIS_WARLOCK); + expect(BigInt(owner)).not.toBe(0n); + }, 30_000); +}); diff --git a/sdk/test/species.test.ts b/sdk/test/species.test.ts new file mode 100644 index 0000000..5115a25 --- /dev/null +++ b/sdk/test/species.test.ts @@ -0,0 +1,104 @@ +import { describe, expect, it } from 'vitest'; +import { + BeastType, + GENESIS_SPECIES_NAMES, + PREFIX_NAMES, + SUFFIX_NAMES, + decodeTokenId, + fullBeastName, + genesisSpeciesName, + genesisTier, + genesisType, + prefixName, + suffixName, +} from '../src/index.js'; + +describe('generated tables', () => { + it('has the exact table sizes the contract does', () => { + expect(GENESIS_SPECIES_NAMES).toHaveLength(75); + expect(PREFIX_NAMES).toHaveLength(69); + expect(SUFFIX_NAMES).toHaveLength(18); + }); + + it('contains no empty entries', () => { + for (const table of [GENESIS_SPECIES_NAMES, PREFIX_NAMES, SUFFIX_NAMES]) { + expect(table.every((n) => n.length > 0)).toBe(true); + } + }); + + it('keeps every name inside a felt252', () => { + const encoder = new TextEncoder(); + for (const table of [GENESIS_SPECIES_NAMES, PREFIX_NAMES, SUFFIX_NAMES]) { + for (const name of table) expect(encoder.encode(name).length).toBeLessThanOrEqual(31); + } + }); +}); + +describe('genesis species traits', () => { + // Anchors taken from the contract's own unit tests in beast_manager.cairo. + it.each([ + [1n, 'Warlock', 1, BeastType.Magic], + [3n, 'Jiangshi', 1, BeastType.Magic], + [25n, 'Gnome', 5, BeastType.Magic], + [42n, 'Fenrir', 4, BeastType.Hunter], + [75n, undefined, 5, BeastType.Brute], + ])('resolves species %s', (id, name, tier, type) => { + if (name) expect(genesisSpeciesName(id as bigint)).toBe(name); + expect(genesisTier(id as bigint)).toBe(tier); + expect(genesisType(id as bigint)).toBe(type); + }); + + it('lays tiers out in five-wide groups within each type block', () => { + for (let id = 1; id <= 75; id++) { + const expected = Math.floor(((id - 1) % 25) / 5) + 1; + expect(genesisTier(BigInt(id))).toBe(expected); + } + }); + + it('splits types into three blocks of 25', () => { + expect(genesisType(25n)).toBe(BeastType.Magic); + expect(genesisType(26n)).toBe(BeastType.Hunter); + expect(genesisType(50n)).toBe(BeastType.Hunter); + expect(genesisType(51n)).toBe(BeastType.Brute); + }); + + it('refuses community species, which resolve through the registry', () => { + expect(() => genesisSpeciesName(76n)).toThrow(/not a genesis species/); + expect(() => genesisTier(76n)).toThrow(/not a genesis species/); + }); +}); + +describe('affixes', () => { + it('matches the contract anchors', () => { + expect(prefixName(1)).toBe('Agony'); + expect(suffixName(1)).toBe('Bane'); + expect(suffixName(2)).toBe('Root'); + }); + + it('returns null for the Genesis Beast’s absent affixes', () => { + expect(prefixName(0)).toBeNull(); + expect(suffixName(0)).toBeNull(); + }); + + it('rejects out-of-range affixes', () => { + expect(() => prefixName(70)).toThrow(RangeError); + expect(() => suffixName(19)).toThrow(RangeError); + }); +}); + +describe('full names', () => { + it('renders a genesis beast as the bare species name', () => { + expect(fullBeastName(decodeTokenId(0x7006400010000000000000000001n))).toBe('Warlock'); + }); + + it('reproduces the name the Sepolia contract rendered', () => { + // The deployed contract returned: "Agony Bane" Gloomfang + const beast = decodeTokenId(0x2e0064000a081000000000000004cn); + expect(fullBeastName(beast, 'Gloomfang')).toBe('"Agony Bane" Gloomfang'); + }); + + it('requires a species name for community species', () => { + const beast = decodeTokenId(0x2e0064000a081000000000000004cn); + expect(() => fullBeastName(beast)).toThrow(/not a genesis species/); + }); +}); diff --git a/sdk/test/tokenId.test.ts b/sdk/test/tokenId.test.ts new file mode 100644 index 0000000..804b482 --- /dev/null +++ b/sdk/test/tokenId.test.ts @@ -0,0 +1,172 @@ +import { describe, expect, it } from 'vitest'; +import { + BeastType, + TokenIdError, + beastPower, + decodeTokenId, + encodeTokenId, + genesisBeast, + isGenesis, + isGenesisSpecies, + type Beast, +} from '../src/index.js'; + +/** + * These two IDs were produced by the deployed contract on Sepolia, not by + * this SDK — see `docs/sepolia-v3-deployment.md`. They are the anchor that + * proves the TS layout matches `pack_to_u256`; everything else here is + * self-consistency. + */ +const ONCHAIN_GENESIS_WARLOCK = 0x7006400010000000000000000001n; +const ONCHAIN_GLOOMFANG = 0x2e0064000a081000000000000004cn; + +describe('on-chain parity', () => { + it('decodes the Sepolia genesis Warlock token', () => { + const beast = decodeTokenId(ONCHAIN_GENESIS_WARLOCK); + expect(beast).toEqual({ + id: 1n, + prefix: 0, + suffix: 0, + level: 1, + health: 100, + shiny: 1, + animated: 1, + tier: 1, + beastType: BeastType.Magic, + }); + expect(isGenesis(beast)).toBe(true); + }); + + it('decodes the Sepolia "Agony Bane" Gloomfang token', () => { + const beast = decodeTokenId(ONCHAIN_GLOOMFANG); + expect(beast).toEqual({ + id: 76n, + prefix: 1, + suffix: 1, + level: 10, + health: 100, + shiny: 0, + animated: 1, + tier: 3, + beastType: BeastType.Hunter, + }); + expect(isGenesis(beast)).toBe(false); + // The contract reported Power 30 for this token. + expect(beastPower(beast)).toBe(30); + }); + + it('re-encodes both on-chain tokens byte for byte', () => { + for (const tokenId of [ONCHAIN_GENESIS_WARLOCK, ONCHAIN_GLOOMFANG]) { + expect(encodeTokenId(decodeTokenId(tokenId))).toBe(tokenId); + } + }); +}); + +describe('round trips', () => { + it('survives the maximum value in every field', () => { + const beast: Beast = { + id: (1n << 64n) - 1n, + prefix: 69, + suffix: 18, + level: 65535, + health: 65535, + shiny: 1, + animated: 1, + tier: 5, + beastType: BeastType.Brute, + }; + expect(decodeTokenId(encodeTokenId(beast))).toEqual(beast); + }); + + it('stays inside 116 bits at maximum', () => { + const maxId = encodeTokenId({ + id: (1n << 64n) - 1n, + prefix: 69, + suffix: 18, + level: 65535, + health: 65535, + shiny: 1, + animated: 1, + tier: 5, + beastType: BeastType.Brute, + }); + expect(maxId >> 116n).toBe(0n); + // Fits a u128, which is what makes these IDs cheap for clients. + expect(maxId < 1n << 128n).toBe(true); + }); + + it('accepts hex strings and numbers', () => { + expect(decodeTokenId('0x7006400010000000000000000001').id).toBe(1n); + expect(decodeTokenId(ONCHAIN_GENESIS_WARLOCK.toString()).id).toBe(1n); + }); +}); + +describe('validation', () => { + const valid: Beast = { + id: 3n, + prefix: 1, + suffix: 2, + level: 10, + health: 100, + shiny: 0, + animated: 0, + tier: 1, + beastType: BeastType.Magic, + }; + + it('rejects a zero species ID', () => { + expect(() => encodeTokenId({ ...valid, id: 0n })).toThrow(TokenIdError); + expect(() => decodeTokenId(0n)).toThrow(/species ID must not be zero/); + }); + + it('rejects residual high bits', () => { + expect(() => decodeTokenId(1n << 116n)).toThrow(/residual high bits/); + }); + + it('rejects half-set affixes in both directions', () => { + // The (id, 0, 0) slot is reserved for the Genesis Beast, so a Beast may + // have both affixes or neither — never one. + expect(() => encodeTokenId({ ...valid, prefix: 0 })).toThrow(/invalid affix combo/); + expect(() => encodeTokenId({ ...valid, suffix: 0 })).toThrow(/invalid affix combo/); + }); + + it('accepts a genesis beast with neither affix', () => { + expect(() => encodeTokenId({ ...valid, prefix: 0, suffix: 0 })).not.toThrow(); + }); + + it('rejects out-of-range traits', () => { + expect(() => encodeTokenId({ ...valid, tier: 0 })).toThrow(/tier out of range/); + expect(() => encodeTokenId({ ...valid, tier: 6 })).toThrow(/tier out of range/); + expect(() => encodeTokenId({ ...valid, prefix: 70 })).toThrow(/prefix out of range/); + expect(() => encodeTokenId({ ...valid, suffix: 19 })).toThrow(/suffix out of range/); + expect(() => encodeTokenId({ ...valid, beastType: 3 as BeastType })).toThrow( + /beast type out of range/, + ); + }); + + it('rejects a decoded tier of zero', () => { + // Tier 0 is unreachable through encode, so build the ID by hand. + const raw = 1n | (1n << 64n) | (1n << 71n); + expect(() => decodeTokenId(raw)).toThrow(/tier out of range/); + }); +}); + +describe('derived helpers', () => { + it('caps power at u16', () => { + expect(beastPower({ ...genesisBeast(1n, 1, BeastType.Magic), level: 65535 })).toBe(65535); + }); + + it('computes power as level * (6 - tier)', () => { + for (let tier = 1; tier <= 5; tier++) { + const beast = { ...genesisBeast(1n, tier, BeastType.Magic), level: 10 }; + expect(beastPower(beast)).toBe(10 * (6 - tier)); + } + }); + + it('classifies genesis vs community species', () => { + expect(isGenesisSpecies(1n)).toBe(true); + expect(isGenesisSpecies(75n)).toBe(true); + expect(isGenesisSpecies(76n)).toBe(false); + expect(isGenesisSpecies(0n)).toBe(false); + }); +}); diff --git a/sdk/test/validation.test.ts b/sdk/test/validation.test.ts new file mode 100644 index 0000000..9d30959 --- /dev/null +++ b/sdk/test/validation.test.ts @@ -0,0 +1,122 @@ +import { describe, expect, it } from 'vitest'; +import { + validateArtSet, + validateFactoryArt, + validateRenderableArt, + validateSpeciesName, + validateTier, +} from '../src/index.js'; + +describe('species names', () => { + it('accepts the charset the contract allows', () => { + for (const name of ["Warlock", "Fire Drake", "K9", "Ol' One-Eye", 'x', 'A name that is 31 bytes long ok']) { + expect(validateSpeciesName(name).valid).toBe(true); + } + }); + + it('rejects the injection characters the contract guards against', () => { + // components_to_json and the SVG builder embed names unescaped, so these + // would break every token's metadata for that species. + for (const name of ['bad"name', 'bad\\name', '', 'a,b', 'ab']) { + expect(validateSpeciesName(name).valid).toBe(false); + } + }); + + it('rejects empty and edge-space names', () => { + expect(validateSpeciesName('').valid).toBe(false); + expect(validateSpeciesName(' Warlock').valid).toBe(false); + expect(validateSpeciesName('Warlock ').valid).toBe(false); + }); + + it('rejects names past the felt252 limit', () => { + expect(validateSpeciesName('a'.repeat(31)).valid).toBe(true); + expect(validateSpeciesName('a'.repeat(32)).valid).toBe(false); + }); + + it('counts bytes, not code points', () => { + // Multi-byte characters are outside the charset anyway, but the length + // check must not be fooled into thinking they fit. + expect(validateSpeciesName('é'.repeat(20)).valid).toBe(false); + }); +}); + +describe('renderable art', () => { + it('accepts every allowed media type', () => { + for (const uri of [ + 'data:image/png;base64,iVBORw0KGgo=', + 'data:image/gif;base64,R0lGODlhAQAB', + 'data:image/webp;base64,UklGRhIAAABX', + 'data:image/svg+xml;base64,PHN2Zy8+', + ]) { + expect(validateRenderableArt(uri).valid).toBe(true); + } + }); + + it('rejects non-image media types', () => { + expect(validateRenderableArt('data:text/html;base64,PHNjcmlwdD4=').valid).toBe(false); + }); + + it('rejects URL-encoded SVG, which carries raw markup', () => { + expect(validateRenderableArt('data:image/svg+xml,').valid).toBe(false); + }); + + it('rejects an attribute escape', () => { + // The art is embedded inside a single-quoted src='...' attribute. + expect(validateRenderableArt("data:image/png;base64,AAAA'AAA").valid).toBe(false); + }); + + it('rejects payloads that are not 4-aligned', () => { + expect(validateRenderableArt('data:image/png;base64,AAAAA').valid).toBe(false); + }); + + it('rejects an empty payload', () => { + expect(validateRenderableArt('data:image/png;base64,').valid).toBe(false); + }); + + it('rejects interior padding', () => { + expect(validateRenderableArt('data:image/png;base64,AA=ABBBB').valid).toBe(false); + }); +}); + +describe('factory art', () => { + it('accepts real PNG and both GIF versions', () => { + expect(validateFactoryArt('data:image/png;base64,iVBORw0KGgoAAAA1', 'png').valid).toBe(true); + expect(validateFactoryArt('data:image/gif;base64,R0lGODdhAAA1', 'gif').valid).toBe(true); + expect(validateFactoryArt('data:image/gif;base64,R0lGODlhAAA1', 'gif').valid).toBe(true); + }); + + it('rejects a payload without PNG magic bytes', () => { + expect(validateFactoryArt('data:image/png;base64,AAAAAAAAAAAA', 'png').valid).toBe(false); + }); + + it('rejects a truncated GIF signature', () => { + // "R0lGODAAAAAA" decodes to the invalid header GIF80; the version + // characters have to be checked, not just the "R0lGOD" stem. + expect(validateFactoryArt('data:image/gif;base64,R0lGODAAAAAA', 'gif').valid).toBe(false); + }); + + it('rejects a GIF submitted as a PNG', () => { + expect(validateFactoryArt('data:image/gif;base64,R0lGODdhAAA1', 'png').valid).toBe(false); + }); + + it('validates a whole set and names the offending variant', () => { + const good = { + pngRegular: 'data:image/png;base64,iVBORw0KGgoAAAA1', + pngShiny: 'data:image/png;base64,iVBORw0KGgoAAAA2', + gifRegular: 'data:image/gif;base64,R0lGODdhAAA1', + gifShiny: 'data:image/gif;base64,R0lGODdhAAA2', + }; + expect(validateArtSet(good).valid).toBe(true); + + const bad = validateArtSet({ ...good, gifShiny: 'data:image/gif;base64,AAAAAAAA' }); + expect(bad.valid).toBe(false); + expect(bad.error).toMatch(/^Shiny GIF:/); + }); +}); + +describe('tier', () => { + it('accepts 1 through 5 only', () => { + for (const tier of [1, 2, 3, 4, 5]) expect(validateTier(tier).valid).toBe(true); + for (const tier of [0, 6, -1, 1.5]) expect(validateTier(tier).valid).toBe(false); + }); +}); diff --git a/sdk/tsconfig.build.json b/sdk/tsconfig.build.json new file mode 100644 index 0000000..1c207e7 --- /dev/null +++ b/sdk/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "src" + }, + "include": ["src/**/*"] +} diff --git a/sdk/tsconfig.json b/sdk/tsconfig.json new file mode 100644 index 0000000..25b8ca1 --- /dev/null +++ b/sdk/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ES2022", "DOM"], + "strict": true, + "noUncheckedIndexedAccess": false, + "esModuleInterop": true, + "skipLibCheck": true, + "declaration": true, + "outDir": "dist" + }, + "include": ["src/**/*", "test/**/*"] +} diff --git a/sdk/vitest.config.ts b/sdk/vitest.config.ts new file mode 100644 index 0000000..43e56f4 --- /dev/null +++ b/sdk/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + include: ['test/**/*.test.ts'], + }, +}); From a4ead47e679ab5f5bfbba1cc2e4cd274a480bda4 Mon Sep 17 00:00:00 2001 From: loothero Date: Fri, 31 Jul 2026 20:11:53 -0700 Subject: [PATCH 2/8] Support both Cartridge Controller and injected wallets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Connect button called `connect({ connector: connectors[0] })` with Controller as the only option and no error handling, so any failure was invisible — the button simply appeared dead. - Wallet picker listing Controller alongside injected wallets. Ready (formerly Argent) and Braavos are surfaced as recommended even when not installed, so the choice is visible rather than hidden. - `useInjectedConnectors` scans window.starknet, so connector construction moved into a WalletProvider component that renders StarknetConfig. - Connection failures are shown in the modal. A wallet whose extension is absent is disabled and labelled "Not detected" rather than silently doing nothing when clicked. - Footer now names the network, so which chain the app is pointed at is never a guess. Also fixes the connect-modal styles landing in src/styles.css at the repo root instead of app/src/styles.css, which left the modal rendering as an unstyled full-width block below the page content. Co-Authored-By: Claude Opus 5 (1M context) --- app/scripts/smoke.mjs | 16 +++++ app/src/App.tsx | 13 ++-- app/src/components/ConnectModal.tsx | 108 ++++++++++++++++++++++++++++ app/src/lib/WalletProvider.tsx | 47 ++++++++++++ app/src/lib/chain.ts | 45 ++++++------ app/src/main.tsx | 18 +---- app/src/styles.css | 88 +++++++++++++++++++++++ 7 files changed, 293 insertions(+), 42 deletions(-) create mode 100644 app/src/components/ConnectModal.tsx create mode 100644 app/src/lib/WalletProvider.tsx diff --git a/app/scripts/smoke.mjs b/app/scripts/smoke.mjs index 6603a8c..5ef6961 100644 --- a/app/scripts/smoke.mjs +++ b/app/scripts/smoke.mjs @@ -46,5 +46,21 @@ console.log('badges:', await page.locator('.badge').allTextContents()); console.log('read-only notice:', JSON.stringify(await page.textContent('.notice').catch(() => null))); await page.screenshot({ path: 'smoke-dashboard.png', fullPage: true }); +// Wallet picker: both wallet families must be offered, and a wallet whose +// extension is absent must say so rather than fail silently. +await page.click('.brand'); +await page.waitForTimeout(500); +await page.click('button.primary:has-text("Connect")'); +await page.waitForSelector('.modal', { state: 'visible', timeout: 5000 }); +const wallets = await page.locator('.wallet__name').allTextContents(); +const states = await page.locator('.wallet__state').allTextContents(); +console.log('wallets offered:', wallets.map((w, i) => `${w}${states[i] ? ` (${states[i]})` : ''}`)); +// A centred fixed overlay: narrow, and vertically centred in the viewport +// whatever the page scroll position. +const box = await page.locator('.modal').boundingBox(); +const vh = page.viewportSize().height; +const centred = Math.abs(box.y + box.height / 2 - vh / 2) < 40; +console.log('modal is a centred overlay:', box.width <= 400 && centred); + console.log('CONSOLE ERRORS:', errors.length ? errors.slice(0, 4) : 'none'); await browser.close(); diff --git a/app/src/App.tsx b/app/src/App.tsx index 9d55972..0d2ae7b 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -1,4 +1,4 @@ -import { useAccount, useConnect, useDisconnect } from '@starknet-react/core'; +import { useAccount, useDisconnect } from '@starknet-react/core'; import { BeastsClient, FIRST_COMMUNITY_ID, @@ -6,6 +6,7 @@ import { } from '@provable-games/beasts-sdk'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { ADDRESSES, provider } from './lib/chain'; +import { ConnectModal } from './components/ConnectModal'; import { Dashboard } from './components/Dashboard'; import { RegisterForm, type RegistrationInput } from './components/RegisterForm'; @@ -13,9 +14,9 @@ type View = { kind: 'register' } | { kind: 'species'; id: bigint }; export function App() { const { address, account } = useAccount(); - const { connect, connectors } = useConnect(); const { disconnect } = useDisconnect(); + const [connecting, setConnecting] = useState(false); const [view, setView] = useState({ kind: 'register' }); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(); @@ -99,11 +100,11 @@ export function App() { {address ? ( - - Registry {shortAddr(ADDRESSES.registry)} · Collection{' '} + Sepolia · Registry {shortAddr(ADDRESSES.registry)} · Collection{' '} {shortAddr(ADDRESSES.nft)} + + {connecting && setConnecting(false)} />} ); } diff --git a/app/src/components/ConnectModal.tsx b/app/src/components/ConnectModal.tsx new file mode 100644 index 0000000..579ce2b --- /dev/null +++ b/app/src/components/ConnectModal.tsx @@ -0,0 +1,108 @@ +import { useConnect } from '@starknet-react/core'; +import type { Connector } from '@starknet-react/core'; +import { useState } from 'react'; + +interface Props { + onClose: () => void; +} + +/** + * Wallet picker. + * + * Connectors arrive from `WalletProvider`: Cartridge Controller first (it + * needs no extension, which is the likely case for a first-time artist), then + * any injected wallet. Recommended-but-not-installed wallets are still listed + * so the choice is visible rather than hidden — clicking one sends the artist + * to its download page, which is `InjectedConnector`'s own behaviour. + * + * Connection failures are shown here. Swallowing them is what makes a Connect + * button look broken. + */ +export function ConnectModal({ onClose }: Props) { + const { connect, connectors } = useConnect(); + const [pending, setPending] = useState(null); + const [error, setError] = useState(null); + + async function pick(connector: Connector) { + setPending(connector.id); + setError(null); + try { + await connect({ connector }); + onClose(); + } catch (e) { + setError(describe(e)); + } finally { + setPending(null); + } + } + + return ( +
+
e.stopPropagation()}> +
+

Connect a wallet

+ +
+ +

+ You need Sepolia STRK to register a Beast. Browsing and previewing + work without a wallet. +

+ +
    + {connectors.map((connector) => { + // Controller runs in a hosted iframe, so it is always available; + // injected wallets are only there if their extension is. + const installed = connector.available(); + return ( +
  • + +
  • + ); + })} +
+ + {connectors.some((c) => !c.available()) && ( +

+ Wallets marked “Not detected” need their browser extension + installed. Install it, then reload this page. +

+ )} + + {error &&

{error}

} +
+
+ ); +} + +function WalletIcon({ connector }: { connector: Connector }) { + const icon = connector.icon; + const src = typeof icon === 'string' ? icon : (icon?.dark ?? icon?.light); + if (!src) return ; + return ; +} + +function describe(error: unknown): string { + const message = error instanceof Error ? error.message : String(error); + if (/reject|denied|cancel/i.test(message)) return 'Connection cancelled.'; + if (/not found|no wallet|unavailable/i.test(message)) { + return 'That wallet is not installed in this browser.'; + } + return message; +} diff --git a/app/src/lib/WalletProvider.tsx b/app/src/lib/WalletProvider.tsx new file mode 100644 index 0000000..da3a732 --- /dev/null +++ b/app/src/lib/WalletProvider.tsx @@ -0,0 +1,47 @@ +import { + StarknetConfig, + braavos, + jsonRpcProvider, + ready, + useInjectedConnectors, + voyager, +} from '@starknet-react/core'; +import type { PropsWithChildren } from 'react'; +import { RPC_URL, chains, controllerConnector } from './chain'; + +/** + * Wallet wiring for the app. + * + * Two kinds of wallet, deliberately both supported: Cartridge Controller + * (no extension, good for a first-time artist) and any injected browser + * wallet — Ready (formerly Argent) and Braavos are surfaced as recommended + * even when not installed, so the picker shows what is possible rather than + * only what is present. + * + * `useInjectedConnectors` scans `window.starknet*`, so it must run inside a + * component; the connector list is then handed to `StarknetConfig` as a prop. + */ +export function WalletProvider({ children }: PropsWithChildren) { + const { connectors: injected } = useInjectedConnectors({ + recommended: [ready(), braavos()], + includeRecommended: 'always', + order: 'alphabetical', + }); + + // `publicProvider()` pins RPC spec 0.8.1, which starknet 9.x dropped — it + // throws before the tree ever renders. Naming the node lets the provider + // negotiate whatever that node actually speaks. + const rpc = () => ({ nodeUrl: RPC_URL }); + + return ( + + {children} + + ); +} diff --git a/app/src/lib/chain.ts b/app/src/lib/chain.ts index 1240468..2f00f34 100644 --- a/app/src/lib/chain.ts +++ b/app/src/lib/chain.ts @@ -12,37 +12,38 @@ export const ADDRESSES = { registry: import.meta.env.VITE_BEASTS_REGISTRY ?? SEPOLIA_ADDRESSES.registry, }; +/** Sepolia only. Everything this app talks to is deployed there. */ export const chains = [sepolia]; export const provider = () => new RpcProvider({ nodeUrl: RPC_URL }); /** - * Cartridge Controller with the registry entrypoints pre-approved, so an - * artist signs once and can then iterate on their species — update art, rotate - * the minter, refresh metadata — without a popup for every change. + * Cartridge Controller with the registry's *management* entrypoints + * pre-approved, so an artist signs once and can then iterate on their species — + * update art, rotate the minter, refresh metadata — without a popup for every + * change. * * `register_beast_with_art` is deliberately NOT in the session policy: it * mints the artist's provenance token and permanently assigns a species ID, so * it should always be an explicit, visible signature. */ -export const connectors = [ - new ControllerConnector({ - chains: [{ rpcUrl: RPC_URL }], - // Must be 0x-prefixed hex; the bare digits parse as neither hex nor decimal. - defaultChainId: `0x${sepolia.id.toString(16)}`, - policies: { - contracts: { - [ADDRESSES.registry]: { - name: 'Beast Registry', - methods: [ - { name: 'Update art', entrypoint: 'update_art' }, - { name: 'Set minter', entrypoint: 'set_minter' }, - { name: 'Set art provider', entrypoint: 'set_art_provider' }, - { name: 'Refresh metadata', entrypoint: 'notify_art_updated' }, - { name: 'Set stats source', entrypoint: 'set_stats_source' }, - ], - }, +export const controllerConnector = new ControllerConnector({ + chains: [{ rpcUrl: RPC_URL }], + // Must be 0x-prefixed hex; the bare digits parse as neither hex nor decimal. + defaultChainId: `0x${sepolia.id.toString(16)}`, + propagateSessionErrors: true, + policies: { + contracts: { + [ADDRESSES.registry]: { + name: 'Beast Registry', + methods: [ + { name: 'Update art', entrypoint: 'update_art' }, + { name: 'Set minter', entrypoint: 'set_minter' }, + { name: 'Set art provider', entrypoint: 'set_art_provider' }, + { name: 'Refresh metadata', entrypoint: 'notify_art_updated' }, + { name: 'Set stats source', entrypoint: 'set_stats_source' }, + ], }, }, - }), -]; + }, +}); diff --git a/app/src/main.tsx b/app/src/main.tsx index fdd5c03..7aac99c 100644 --- a/app/src/main.tsx +++ b/app/src/main.tsx @@ -1,25 +1,13 @@ -import { StarknetConfig, jsonRpcProvider, voyager } from '@starknet-react/core'; import React from 'react'; import ReactDOM from 'react-dom/client'; import { App } from './App'; -import { RPC_URL, chains, connectors } from './lib/chain'; +import { WalletProvider } from './lib/WalletProvider'; import './styles.css'; -// `publicProvider()` pins RPC spec 0.8.1, which starknet 9.x no longer -// supports — it throws before the tree ever renders. Supplying the node URL -// directly lets the provider negotiate whatever the node actually speaks. -const rpc = () => ({ nodeUrl: RPC_URL }); - ReactDOM.createRoot(document.getElementById('root')!).render( - + - + , ); diff --git a/app/src/styles.css b/app/src/styles.css index 62464e9..11b1387 100644 --- a/app/src/styles.css +++ b/app/src/styles.css @@ -550,3 +550,91 @@ select:focus { font-size: 12.5px; color: var(--muted); } + +.modal__hint { + margin: 14px 0 0; + font-size: 12.5px; +} + +/* ---------------------------------------------------------- connect modal */ + +.modal-backdrop { + position: fixed; + inset: 0; + background: #000000b8; + display: grid; + place-items: center; + padding: 20px; + z-index: 50; +} + +.modal { + background: var(--panel); + border: 1px solid var(--line); + border-radius: 14px; + padding: 22px; + width: 100%; + max-width: 380px; + box-shadow: 0 20px 60px #00000080; +} + +.modal__header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 6px; +} + +.modal__header h3 { + margin: 0; + font-size: 17px; +} + +.modal__close { + background: none; + border: 0; + color: var(--muted); + font-size: 24px; + line-height: 1; + padding: 0 4px; + cursor: pointer; +} + +.wallets { + list-style: none; + margin: 18px 0 0; + padding: 0; + display: grid; + gap: 8px; +} + +.wallet { + display: flex; + align-items: center; + gap: 11px; + width: 100%; + text-align: left; + padding: 12px 14px; +} + +.wallet__icon { + width: 24px; + height: 24px; + border-radius: 6px; + object-fit: contain; + flex: none; +} + +.wallet__icon--blank { + background: var(--panel-2); +} + +.wallet__name { + flex: 1; + font-weight: 500; +} + +.wallet__state { + font-size: 12px; + color: var(--muted); +} From bbc06259e82f4bc0850c716f56e9bbd6352b5f4f Mon Sep 17 00:00:00 2001 From: loothero Date: Fri, 31 Jul 2026 20:22:25 -0700 Subject: [PATCH 3/8] Stop the preview card cropping square artwork MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A percentage height against an `aspect-ratio` parent resolves to `auto`, so a square Beast sized itself from its own 1:1 ratio instead of the frame's: a 32x32 image rendered 268x268 inside a 268x175 box and `overflow: hidden` cropped the top and bottom. Artists saw a horizontal slice of their work. Absolute inset gives the image a definite box to fit inside, so `object-fit: contain` scales the whole thing down and centres it — matching the contract's own layout, which draws a square art region inside a wider frame. The smoke test now uploads a 32x32 fixture with a border on all four sides and asserts the rendered image fits its frame. The border is the tell: any crop loses an edge. Co-Authored-By: Claude Opus 5 (1M context) --- app/scripts/smoke.mjs | 24 ++++++++++++++++++++++++ app/src/styles.css | 7 +++++++ 2 files changed, 31 insertions(+) diff --git a/app/scripts/smoke.mjs b/app/scripts/smoke.mjs index 5ef6961..74a5a48 100644 --- a/app/scripts/smoke.mjs +++ b/app/scripts/smoke.mjs @@ -1,4 +1,17 @@ import { chromium } from 'playwright'; +import { mkdtempSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; + +// 32x32 PNG: magenta border on all four sides, green corner-to-corner +// diagonal. Real Beast art is this size, and the border is the tell — if the +// preview crops, an edge goes missing. +const TEST_PNG = + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAiklEQVR4nLXNSw6AIAyEYQ7B2vvfEk1sULFAHzOZf9FVv9JKoyar9WAk76+LZDwAyfgADGME4IYCYA0dABpTAGWsAIixAfLGHkgaJiBjWIGw4QBihg8IGG7Aa0QAlxEE7EYcMBopwGJkga0BANYGBlgYMGBmIAHVAAN/Aw8MBgV4GyygG0TgNmTUTqHjAu38soSbAAAAAElFTkSuQmCC'; + +const fixtureDir = mkdtempSync(join(tmpdir(), 'beasts-smoke-')); +const pngPath = join(fixtureDir, 'test.png'); +writeFileSync(pngPath, Buffer.from(TEST_PNG, 'base64')); const browser = await chromium.launch({ executablePath: @@ -34,6 +47,17 @@ await page.waitForTimeout(200); const power = await page.locator('.stat', { hasText: 'Power' }).textContent(); console.log('tier 1 power (level 10 x 5):', JSON.stringify(power)); +// Preview sizing. A percentage height against an `aspect-ratio` parent +// resolves to `auto`, so a square Beast used to size itself from its own 1:1 +// ratio, overflow the wider frame, and get cropped by `overflow: hidden`. +await page.locator('.art-slot__drop input[type=file]').first().setInputFiles(pngPath); +await page.waitForTimeout(1200); +const artBox = await page.locator('.card__art').boundingBox(); +const imgBox = await page.locator('.card__art img').boundingBox(); +console.log('preview art fits its frame:', + imgBox.height <= artBox.height + 1 && imgBox.width <= artBox.width + 1, + `(img ${Math.round(imgBox.width)}x${Math.round(imgBox.height)} in frame ${Math.round(artBox.width)}x${Math.round(artBox.height)})`); + await page.screenshot({ path: 'smoke-register.png', fullPage: true }); // Dashboard for the live species 76. diff --git a/app/src/styles.css b/app/src/styles.css index 11b1387..bb18253 100644 --- a/app/src/styles.css +++ b/app/src/styles.css @@ -387,6 +387,7 @@ select:focus { } .card__art { + position: relative; aspect-ratio: 220 / 144; background: #000; border-radius: 8px; @@ -395,7 +396,13 @@ select:focus { overflow: hidden; } +/* Absolute inset is what gives the image a definite box to fit inside. + A percentage height against an `aspect-ratio` parent resolves to `auto`, + so a square Beast would size itself from its own 1:1 ratio, overflow the + wider frame, and get cropped top and bottom by `overflow: hidden`. */ .card__art img { + position: absolute; + inset: 0; width: 100%; height: 100%; object-fit: contain; From ff282f1549a12e2cbf3a84fe728d8c444071ab85 Mon Sep 17 00:00:00 2001 From: loothero Date: Fri, 31 Jul 2026 20:43:01 -0700 Subject: [PATCH 4/8] Wire Manage to the species a wallet actually controls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Manage was the submit button of a species-number input, so it did nothing unless you already knew your ID. It now opens a list of everything the connected wallet controls, each card linking into the existing dashboard. Lookup-by-ID survives inside that view for anyone who does know the number. The list keys off the artist role, not the Genesis Beast. The two start together but diverge the moment either is transferred, and the role is what the registry's permissioned entrypoints check — listing by token would offer controls that revert. SDK gains getSpeciesByArtist / getOwnedSpecies, derived from BeastRegistered and ArtistTransferred events rather than by scanning IDs: the registry keeps no artist index and species_count grows without bound. BeastsAddresses gains a required fromBlock, which is a correctness fix rather than an optimisation. Public nodes cap how far back getEvents will look, and the one used here answers an over-wide range with an EMPTY RESULT rather than an error — so scanning from genesis reports "this wallet owns nothing" instead of failing. Sepolia is anchored to the set_nft_address block, a provably safe floor: the registry rejects every registration until the NFT is wired, so no BeastRegistered can predate it. Live tests assert the lookup returns something, which is the guard against that failure mode being silent again. Co-Authored-By: Claude Opus 5 (1M context) --- app/README.md | 18 +++- app/scripts/smoke.mjs | 19 ++-- app/src/App.tsx | 100 ++++++++++---------- app/src/components/MySpecies.tsx | 154 +++++++++++++++++++++++++++++++ app/src/lib/chain.ts | 5 + app/src/styles.css | 107 +++++++++++++++++++++ app/src/vite-env.d.ts | 1 + sdk/README.md | 22 +++++ sdk/src/index.ts | 1 + sdk/src/registry.ts | 110 +++++++++++++++++++++- sdk/test/live.test.ts | 39 ++++++++ 11 files changed, 509 insertions(+), 67 deletions(-) create mode 100644 app/src/components/MySpecies.tsx diff --git a/app/README.md b/app/README.md index 1d4d1c3..723eb5f 100644 --- a/app/README.md +++ b/app/README.md @@ -29,10 +29,20 @@ enforces (media type, base64 structure, PNG/GIF magic bytes) *and* decoded by the browser, because a file that will not decode here renders broken for every holder. Registration mints the artist's Genesis Beast in the same transaction. -**Manage.** Per-species controls: replace art, rotate or pause the minter, lock -either one permanently, opt into kill stats, transfer the artist role, or -graduate to a custom art provider. Everything is artist-only on-chain; the UI -hides what the caller cannot do and the contract is the real gate. +**Manage.** Lists every species the connected wallet holds the artist role for, +with its live art, and opens the per-species controls: replace art, rotate or +pause the minter, lock either one permanently, opt into kill stats, transfer +the artist role, or graduate to a custom art provider. + +The list keys off the **artist role, not the Genesis Beast**. They start +together but diverge the moment either is transferred, and the role is what the +registry's permissioned entrypoints check — listing by token would offer +controls that revert. Everything is artist-only on-chain; the UI hides what the +caller cannot do and the contract is the real gate. + +Art thumbnails come from each species' own provider, which for a custom +provider is arbitrary contract code. One that reverts costs its own thumbnail, +not the whole list. ## The preview card is an approximation diff --git a/app/scripts/smoke.mjs b/app/scripts/smoke.mjs index 74a5a48..c5bfaad 100644 --- a/app/scripts/smoke.mjs +++ b/app/scripts/smoke.mjs @@ -60,22 +60,15 @@ console.log('preview art fits its frame:', await page.screenshot({ path: 'smoke-register.png', fullPage: true }); -// Dashboard for the live species 76. -await page.fill('input[placeholder="Species #"]', '76'); -await page.click('.lookup button'); -await page.waitForTimeout(5000); -console.log('dashboard heading:', JSON.stringify(await page.textContent('.dashboard__header h2').catch(() => null))); -console.log('dashboard meta:', JSON.stringify(await page.textContent('.dashboard__header p').catch(() => null))); -console.log('badges:', await page.locator('.badge').allTextContents()); -console.log('read-only notice:', JSON.stringify(await page.textContent('.notice').catch(() => null))); -await page.screenshot({ path: 'smoke-dashboard.png', fullPage: true }); +// Manage lists the species the connected wallet controls, so with no wallet +// it has to ask for one rather than opening an empty page. +await page.click('button:has-text("Manage")'); +await page.waitForTimeout(800); +console.log('Manage without a wallet prompts connect:', + (await page.locator('.modal').count()) > 0 && (await page.locator('.mine').count()) === 0); // Wallet picker: both wallet families must be offered, and a wallet whose // extension is absent must say so rather than fail silently. -await page.click('.brand'); -await page.waitForTimeout(500); -await page.click('button.primary:has-text("Connect")'); -await page.waitForSelector('.modal', { state: 'visible', timeout: 5000 }); const wallets = await page.locator('.wallet__name').allTextContents(); const states = await page.locator('.wallet__state').allTextContents(); console.log('wallets offered:', wallets.map((w, i) => `${w}${states[i] ? ` (${states[i]})` : ''}`)); diff --git a/app/src/App.tsx b/app/src/App.tsx index 0d2ae7b..7dc32bb 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -1,16 +1,13 @@ import { useAccount, useDisconnect } from '@starknet-react/core'; -import { - BeastsClient, - FIRST_COMMUNITY_ID, - type BeastDefinition, -} from '@provable-games/beasts-sdk'; +import { BeastsClient, type BeastDefinition } from '@provable-games/beasts-sdk'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { ADDRESSES, provider } from './lib/chain'; import { ConnectModal } from './components/ConnectModal'; import { Dashboard } from './components/Dashboard'; +import { MySpecies } from './components/MySpecies'; import { RegisterForm, type RegistrationInput } from './components/RegisterForm'; -type View = { kind: 'register' } | { kind: 'species'; id: bigint }; +type View = { kind: 'register' } | { kind: 'mine' } | { kind: 'species'; id: bigint }; export function App() { const { address, account } = useAccount(); @@ -22,12 +19,8 @@ export function App() { const [error, setError] = useState(); const [definition, setDefinition] = useState(null); const [speciesCount, setSpeciesCount] = useState(null); - const [lookup, setLookup] = useState(''); - const client = useMemo( - () => new BeastsClient(provider(), ADDRESSES, account), - [account], - ); + const client = useMemo(() => new BeastsClient(provider(), ADDRESSES, account), [account]); const refresh = useCallback(async () => { setSpeciesCount(await client.speciesCount().catch(() => null)); @@ -48,6 +41,12 @@ export function App() { void refresh(); }, [refresh]); + // Managing means signing, so a disconnect has to drop out of those views + // rather than leave dead controls on screen. + useEffect(() => { + if (!address && view.kind !== 'register') setView({ kind: 'register' }); + }, [address, view.kind]); + async function register(input: RegistrationInput) { setSubmitting(true); setError(undefined); @@ -71,8 +70,12 @@ export function App() { } } - const isArtist = - !!address && !!definition && BigInt(definition.artist) === BigInt(address); + const isArtist = !!address && !!definition && BigInt(definition.artist) === BigInt(address); + + function openManage() { + if (address) setView({ kind: 'mine' }); + else setConnecting(true); + } return (
@@ -82,22 +85,9 @@ export function App() {
-
{ - e.preventDefault(); - const id = BigInt(lookup || '0'); - if (id >= FIRST_COMMUNITY_ID) setView({ kind: 'species', id }); - }} - > - setLookup(e.target.value.replace(/\D/g, ''))} - /> - -
+ {address ? ( -
)} + + {view.kind === 'species' && + (definition ? ( + <> + + void refresh()} + /> + + ) : ( +
+

{error ?? 'Loading…'}

+ +
+ ))}