From 9e1d4e22e1a07fb9a48f59b8d8c09d4154b7290c Mon Sep 17 00:00:00 2001 From: Gabito Esmiapodo <4015436+gabitoesmiapodo@users.noreply.github.com> Date: Fri, 10 Apr 2026 11:35:24 -0300 Subject: [PATCH 1/3] docs: sync architecture.md with current codebase Update five stale references: - TypeScript 5 -> 6 - Vite 6 + SWC -> Vite 8 + React plugin - Remove nonexistent withWalletStatusVerifier HOC references - Token list sources: remove 1INCH (only CoinGecko exists) - staleTime/gcTime: Infinity -> 1 hour Closes #452 --- architecture.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/architecture.md b/architecture.md index 90c6da52..1f4c23a3 100644 --- a/architecture.md +++ b/architecture.md @@ -10,13 +10,13 @@ | Category | Technology | Notes | |----------|-----------|-------| | Framework | React 19 | StrictMode enabled | -| Language | TypeScript 5 (strict, ESM) | Path aliases: `@/src/*`, `@packageJSON` | +| Language | TypeScript 6 (strict, ESM) | Path aliases: `@/src/*`, `@packageJSON` | | Blockchain | wagmi 2 + viem 2 | Type-safe Ethereum interaction | | Data fetching | TanStack Query 5, graphql-request | Suspense-based contract reads | | Routing | TanStack Router | File-based with auto code-splitting | | UI | Chakra UI 3 + Emotion | Semantic tokens, light/dark mode | | Testing | Vitest + Testing Library | jsdom environment, colocated test files | -| Build | Vite 6 + SWC | Manual chunk splitting for vendors | +| Build | Vite 8 + React plugin | Manual chunk splitting for vendors | | Linting | Biome | Format + lint in one tool | | Env validation | Zod + @t3-oss/env-core | All vars `PUBLIC_` prefixed | @@ -65,7 +65,6 @@ ComponentName/ **HOC patterns:** - `withSuspenseAndRetry(Component)` -- primary pattern for async components; wraps in `QueryErrorResetBoundary` + `ErrorBoundary` + `Suspense` for automatic retry on query failures - `withSuspense(Component)` -- simpler variant without retry -- `withWalletStatusVerifier(Component)` -- gates a component behind wallet connection + chain sync **Contract hooks** (auto-generated by wagmi-cli from ABIs): - `useRead{Contract}{Function}` -- standard read @@ -92,7 +91,7 @@ Four external data paths. Components never call external services directly -- th 3. **Subgraph queries**: `graphql-request` with typed document nodes from `@graphql-codegen` -> TanStack Query cache. Queries live in `src/subgraphs/queries/`, generated types in `src/subgraphs/gql/`. -4. **Token data**: LI.FI SDK (`getChains` -> `getTokens` -> `getTokenBalances`) via `useTokens` hook. Token lists fetched in parallel via `useTokenLists` (Suspense-based, sources: 1INCH, CoinGecko, optional Uniswap default list). Tokens deduplicated by `chainId + address`, native tokens auto-injected per chain. +4. **Token data**: LI.FI SDK (`getChains` -> `getTokens` -> `getTokenBalances`) via `useTokens` hook. Token lists fetched in parallel via `useTokenLists` (Suspense-based, source: CoinGecko, optional Uniswap default list). Tokens deduplicated by `chainId + address`, native tokens auto-injected per chain. ## Routes @@ -117,7 +116,7 @@ Token list URLs ───> fetch + Zod validate ───> Tan Caching strategy: - All async state lives in TanStack Query. Components do not hold async data in local state. -- Token lists: `staleTime: Infinity`, `gcTime: Infinity` (fetched once per session). +- Token lists: `staleTime: 1 hour`, `gcTime: 1 hour`. - Token balances: refreshed every ~32s (`BALANCE_EXPIRATION_TIME`). - Contract reads: Suspense-based -- component suspends until data arrives, then cached normally. @@ -223,7 +222,7 @@ When adding a new provider: place it inside the outermost provider it depends on **Web3 connection state** (`src/hooks/useWeb3Status.tsx`): - `useWeb3Status()` -- returns `{ readOnlyClient, appChainId, address, isWalletConnected, isWalletSynced, switchChain, disconnect, ... }` -- `useWeb3StatusConnected()` -- same but throws if wallet is not connected; use inside components that are already gated by `withWalletStatusVerifier` +- `useWeb3StatusConnected()` -- same but throws if wallet is not connected; callers must ensure the wallet is connected before rendering **Token hooks**: - `useTokens()` -- token list + LI.FI prices + account balances, sorted by balance value @@ -264,6 +263,6 @@ To add a new contract: save the ABI, add it to the contracts array, run `pnpm wa 2. Connected but `walletChainId !== appChainId` -> "Switch to [Network]" button 3. Connected + synced -> renders children -**`withWalletStatusVerifier(Component)`** HOC -- wraps the component with the above logic. Already applied to `TransactionButton` and `SignButton` -- do not double-wrap. +`TransactionButton` and `SignButton` use the `useWalletStatus()` hook directly for inline wallet state checks rather than wrapping with the `WalletStatusVerifier` component. Sync check: `isWalletSynced = isWalletConnected && walletChainId === appChainId`. From 23a5e8adda1edcbb66ca31d4064c64768127e6ba Mon Sep 17 00:00:00 2001 From: Gabito Esmiapodo <4015436+gabitoesmiapodo@users.noreply.github.com> Date: Fri, 10 Apr 2026 12:21:07 -0300 Subject: [PATCH 2/3] docs: fix useWeb3StatusConnected description in architecture.md Move from Web3 connection state section to Wallet Access Control section and correct the file path and throw behavior to match the actual implementation in WalletStatusVerifier.tsx. --- architecture.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/architecture.md b/architecture.md index 1f4c23a3..a3c26022 100644 --- a/architecture.md +++ b/architecture.md @@ -222,7 +222,6 @@ When adding a new provider: place it inside the outermost provider it depends on **Web3 connection state** (`src/hooks/useWeb3Status.tsx`): - `useWeb3Status()` -- returns `{ readOnlyClient, appChainId, address, isWalletConnected, isWalletSynced, switchChain, disconnect, ... }` -- `useWeb3StatusConnected()` -- same but throws if wallet is not connected; callers must ensure the wallet is connected before rendering **Token hooks**: - `useTokens()` -- token list + LI.FI prices + account balances, sorted by balance value @@ -263,6 +262,8 @@ To add a new contract: save the ABI, add it to the contracts array, run `pnpm wa 2. Connected but `walletChainId !== appChainId` -> "Switch to [Network]" button 3. Connected + synced -> renders children +`useWeb3StatusConnected()` (same file) -- companion hook that provides typed connected-wallet status (`address`, `readOnlyClient`, etc.) inside the `` tree. Throws a `DeveloperError` if called outside it. + `TransactionButton` and `SignButton` use the `useWalletStatus()` hook directly for inline wallet state checks rather than wrapping with the `WalletStatusVerifier` component. Sync check: `isWalletSynced = isWalletConnected && walletChainId === appChainId`. From 891f9927ad4365f3e33470f8efc47bd467957140 Mon Sep 17 00:00:00 2001 From: Gabito Esmiapodo <4015436+gabitoesmiapodo@users.noreply.github.com> Date: Fri, 10 Apr 2026 13:48:17 -0300 Subject: [PATCH 3/3] docs: correct chain comparison reference in WalletStatusVerifier docs The fallback cascade step 2 referenced appChainId, but useWalletStatus compares against targetChainId which accounts for the optional chainId prop. Updated wording to reflect the actual behavior. --- architecture.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/architecture.md b/architecture.md index a3c26022..d7d81948 100644 --- a/architecture.md +++ b/architecture.md @@ -259,7 +259,7 @@ To add a new contract: save the ABI, add it to the contracts array, run `pnpm wa **`WalletStatusVerifier`** component (`src/components/sharedComponents/WalletStatusVerifier.tsx`) -- renders a fallback cascade based on wallet state: 1. Not connected -> `ConnectWalletButton` -2. Connected but `walletChainId !== appChainId` -> "Switch to [Network]" button +2. Connected but `walletChainId !== targetChainId` (where `targetChainId` is the optional `chainId` prop if provided, otherwise `appChainId`) -> "Switch to [Network]" button 3. Connected + synced -> renders children `useWeb3StatusConnected()` (same file) -- companion hook that provides typed connected-wallet status (`address`, `readOnlyClient`, etc.) inside the `` tree. Throws a `DeveloperError` if called outside it.