Migrate to @unicitylabs/sphere-sdk 0.10.3#2
Conversation
There was a problem hiding this comment.
Code Review
This pull request upgrades the @unicitylabs/sphere-sdk dependency to version 0.10.3 and adapts the wallet creation, connection, and watcher scripts to the new SDK changes, notably replacing L1 addresses with L3 direct addresses and defaulting to the testnet network. The review feedback suggests dynamically resolving the network in the connection client to support switching to mainnet, adding a fail-fast check in the arena watcher to prevent silent failures when the identity is missing, and explicitly defaulting chainPubkey to null during wallet creation to maintain a consistent JSON schema.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| client = new ConnectClient({ | ||
| transport, dapp: dappMeta, permissions: [...dappPermissions], resumeSessionId, | ||
| network: SPHERE_NETWORKS.testnet2, | ||
| }); |
There was a problem hiding this comment.
Hardcoding SPHERE_NETWORKS.testnet2 in the client-side dApp prevents it from working seamlessly when the server is switched to mainnet. Since the server already injects dynamic configuration like window.__BOXY_ARENA_WALLET, it is highly recommended to also inject the network type (e.g., window.__BOXY_SPHERE_NETWORK) and resolve the network dynamically with a fallback to testnet2.
| client = new ConnectClient({ | |
| transport, dapp: dappMeta, permissions: [...dappPermissions], resumeSessionId, | |
| network: SPHERE_NETWORKS.testnet2, | |
| }); | |
| const networkName = (window as any).__BOXY_SPHERE_NETWORK; | |
| const sphereNetwork = networkName === 'mainnet' ? SPHERE_NETWORKS.mainnet : SPHERE_NETWORKS.testnet2; | |
| client = new ConnectClient({ | |
| transport, dapp: dappMeta, permissions: [...dappPermissions], resumeSessionId, | |
| network: sphereNetwork, | |
| }); |
| const id = sphere.identity; | ||
| console.log( | ||
| `[arena-watcher] Sphere ready — nametag=${id?.nametag ? '@' + id.nametag : '(none)'} ` + | ||
| `l1Address=${id?.l1Address || '?'}`, | ||
| `directAddress=${id?.directAddress || '?'}`, | ||
| ); |
There was a problem hiding this comment.
If sphere.identity is null or undefined, the arena watcher will not be able to monitor incoming transfers for the correct wallet, leading to a silent failure. Adding a fail-fast check here ensures that the server crashes or logs a clear error immediately upon boot if the identity cannot be resolved.
| const id = sphere.identity; | |
| console.log( | |
| `[arena-watcher] Sphere ready — nametag=${id?.nametag ? '@' + id.nametag : '(none)'} ` + | |
| `l1Address=${id?.l1Address || '?'}`, | |
| `directAddress=${id?.directAddress || '?'}`, | |
| ); | |
| const id = sphere.identity; | |
| if (!id) { | |
| throw new Error('[arena-watcher] Sphere ready but no identity was returned. Cannot watch for transfers.'); | |
| } | |
| console.log( | |
| `[arena-watcher] Sphere ready — nametag=${id.nametag ? '@' + id.nametag : '(none)'} ` + | |
| `directAddress=${id.directAddress || '?'}`, | |
| ); |
| directAddress: identity.directAddress ?? null, | ||
| chainPubkey: identity.chainPubkey, |
There was a problem hiding this comment.
If identity.chainPubkey is undefined, the chainPubkey key will be completely omitted from the serialized JSON file. To maintain a consistent schema for arena-wallet.json and prevent potential parsing issues in external tools, it is safer to explicitly default it to null using the nullish coalescing operator.
| directAddress: identity.directAddress ?? null, | |
| chainPubkey: identity.chainPubkey, | |
| directAddress: identity.directAddress ?? null, | |
| chainPubkey: identity.chainPubkey ?? null, |
Bump the SDK from 0.6.0-dev.1 to 0.10.3 (the v1->v2 token-engine cutover line) and adapt the four call sites. Browser connect (src/sphere-connect.ts): every import and method is source-compatible. Connect protocol 2.0 added a network handshake gate - a 0.10.x wallet host rejects with INCOMPATIBLE_NETWORK (4008) unless the dApp declares a `network` whose id matches the wallet's active networkId. Pass SPHERE_NETWORKS.testnet2 (networkId 4, the v2 gateway network the arena wallet runs on). Node side (arena-watcher + scripts): 0.10 removed the L1 layer, so Identity / PeerInfo / DiscoveredAddress no longer expose l1Address - switched the informational reads to directAddress (the L3 DIRECT address). Default SPHERE_NETWORK / --network to testnet (-> testnet2) because mainnet/dev gateways are not cut over to the v2 engine yet and make Sphere.import throw INVALID_CONFIG on boot. Verified: npm install (0.10.3 + auto-resolved libp2p/ipns/multiformats peer deps), tsc --noEmit (no new type errors - the 15 pre-existing Babylon/app errors are unchanged), full client build + server build all clean.
eb4af7d to
a42b448
Compare
Bumps
@unicitylabs/sphere-sdkfrom^0.6.0-dev.1to^0.10.3(the v1→v2 token-engine cutover line) and adapts the four SDK call sites.What changed
package.json/package-lock.json0.6.0-dev.1→0.10.3; npm auto-resolved the new@libp2p/*/ipns/multiformatspeer deps (IPFS-only lazy paths — this app never enables IPFS sync)src/sphere-connect.tsnetwork: SPHERE_NETWORKS.testnet2(networkId 4) toConnectClienttournament/server/arena-watcher.tsl1Address→directAddress(log); defaultSPHERE_NETWORKmainnet→testnetscripts/create-arena-wallet.tsl1Address→directAddress(wallet-JSON record + log); default--networkmainnet→testnetscripts/test-arena-watcher.tsl1Address→directAddress(debug output); defaultSPHERE_NETWORKmainnet→testnetWhy these were the only code changes
I diffed the full 0.6.0-dev.1 vs 0.10.3 type surface for
connect,connect/browser, root, andimpl/nodejs. Every symbol/method/option/event/RPC-method-name the app uses still exists and is shape-compatible, with two exceptions:Identity.l1Addressremoved (v1→v2 engine cutover; also gone fromPeerInfoandDiscoveredAddress). The new on-chain address field isdirectAddress(L3 DIRECT). All six reads were switched.ConnectHostrejects withINCOMPATIBLE_NETWORK (4008)unless the dApp sends anetworkwhose id matches the wallet'snetworkId(verified incheckCompatibility:if (!input.clientNetwork || input.clientNetwork.id !== input.walletNetworkId) fail(...)— omittingnetworkis itself a rejection). The dApp now declaresSPHERE_NETWORKS.testnet2(networkId 4).IncomingTransferandTokenshapes are byte-identical, so the arena-watcher's deposit-crediting math is unchanged. HTML files only touch the unchangedwindow.SphereWalletfacade.Verification
npm install→0.10.3installed, peer deps resolved, lockfile consistentnpm run typecheck→ no new type errors (the 15 pre-existing Babylon.js / app-protocol errors are identical on the base branch — proven by typechecking the pristine tree)npm run build(sdk + game + pages) +npm run build:server→ all clean; theconnect/connect/browserimports bundle against 0.10.3ARENA_WALLET_FILE)These follow from the v2 engine cutover and are network-config concerns, not code:
sphere.unicity.networkmust run Connect protocol 2.0 on networkId 4 (testnet2) for the newnetworkhandshake to pass. If a wallet/gateway is later cut over to a different network, updatenetworkinsphere-connect.tsto match.SPHERE_NETWORK=testnet(→ testnet2, networkId 4) as the Fly secret for the arena-watcher on prod + staging. The new default already lands there if unset; mainnet/dev would makeSphere.importthrowINVALID_CONFIGon boot (caught as non-fatal atserver.ts, but deposit auto-crediting then silently stops).SPHERE_NETWORKmust resolve to the same networkId, and the arena wallet's tokens must live on that network. Incoming transfers are now engine-verified + ownership-checked; cross-network or pre-0.8-wallet (non-V2_TRANSFER) sends are dropped beforetransfer:incomingand credit nothing.