diff --git a/.github/workflows/publish-widgets.yml b/.github/workflows/publish-widgets.yml index b4e103ca..321d76d7 100644 --- a/.github/workflows/publish-widgets.yml +++ b/.github/workflows/publish-widgets.yml @@ -59,6 +59,16 @@ jobs: working-directory: ${{ env.PACKAGE_DIR }} run: npm pack --dry-run + - name: Determine npm dist-tag + id: dist-tag + run: | + VERSION="${{ steps.package.outputs.version }}" + if [[ "$VERSION" == *-rc.* ]] || [[ "$VERSION" == *-beta.* ]] || [[ "$VERSION" == *-alpha.* ]]; then + echo "tag=rc" >> "$GITHUB_OUTPUT" + else + echo "tag=latest" >> "$GITHUB_OUTPUT" + fi + - name: Publish package with trusted publishing working-directory: ${{ env.PACKAGE_DIR }} - run: npm publish --access public + run: npm publish --access public --tag ${{ steps.dist-tag.outputs.tag }} diff --git a/README.md b/README.md index 397538a8..80659338 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,7 @@ function buildDepositExecuteConfig( { + let closed = false; + logOnramp("provider.return_page", { hasOpener: Boolean(window.opener) }); + + const closePage = () => { + if (closed) return; + closed = true; + logOnramp("provider.return_page.close"); + window.close(); + }; + + const handleMessage = (event: MessageEvent) => { + if ( + event.source !== window.opener || + event.data !== ONRAMP_SUCCESS_ACK_MESSAGE + ) + return; + logOnramp("provider.return_page.acknowledged"); + closePage(); + }; + + window.addEventListener("message", handleMessage); + const closeTimeout = window.setTimeout(closePage, 3000); + + try { + window.opener?.postMessage(ONRAMP_SUCCESS_MESSAGE, "*"); + } catch { + // The provider can return without an opener in some browser flows. + } + + return () => { + window.removeEventListener("message", handleMessage); + window.clearTimeout(closeTimeout); + }; + }, []); + + return ( +
+ Returning to payment status. Keep the original page open to finish your + deposit. +
+ ); +} diff --git a/components/showcase/nexus-widget-deposit-showcase.tsx b/components/showcase/nexus-widget-deposit-showcase.tsx index 9427be90..fc425c1b 100644 --- a/components/showcase/nexus-widget-deposit-showcase.tsx +++ b/components/showcase/nexus-widget-deposit-showcase.tsx @@ -12,6 +12,7 @@ import { } from "viem"; import { useAccount } from "wagmi"; import { useConnectWalletClick } from "../helpers/use-connect-wallet-click"; +import { cn } from "@/lib/utils"; import { NexusWidgetRenderModeToggle, type NexusWidgetRenderMode, @@ -223,29 +224,15 @@ const resolveDepositAddress = (opportunity: DepositShowcaseOpportunity) => { const OPPORTUNITIES = { // 1. Aave on Arbitrum "aave-arbitrum": { - label: "Aave - Arbitrum", + label: "Aave - Optimism", protocol: "Aave", depositTargetLogo: "https://files.availproject.org/uploads/2026-04-16/aave.svg", - chainId: 42161, - tokenSymbol: "USD₮0", - tokenAddress: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9" as const, + chainId: 10, + tokenSymbol: "USDC", + tokenAddress: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85" as const, tokenDecimals: 6, - tokenLogo: "https://arbiscan.io/token/images/centre-usdc_28.png", - tokens: [ - { - address: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", - decimals: 6, - logo: "https://arbiscan.io/token/images/usdt0_64.png", - symbol: "USD₮0", - }, - { - address: "0xba5DdD1f9d7F570dc94a51479a000E3BCE967196", - decimals: 18, - logo: "https://arbiscan.io/token/images/aave_32.svg", - symbol: "AAVE", - }, - ], + tokenLogo: "https://optimistic.etherscan.io/token/images/usdc_32.png", executeDeposit: ( symbol: string, tokenAddress: `0x${string}`, @@ -269,46 +256,28 @@ const OPPORTUNITIES = { }, // 2. Aave on Ethereum - "aave-ethereum": { - label: "Aave - Ethereum", + "aave-bsc": { + label: "Aave - BSC", protocol: "Aave", depositTargetLogo: "https://files.availproject.org/uploads/2026-04-16/aave.svg", - chainId: 1, + chainId: 56, tokenSymbol: "USDC", - tokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as const, - tokenDecimals: 6, - tokenLogo: "https://etherscan.io/token/images/usdc_ofc_32.svg", + tokenAddress: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d" as const, + tokenDecimals: 18, + tokenLogo: "https://bscscan.com/token/images/centre-usdc_28.png", tokens: [ { - address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - decimals: 6, - logo: "https://etherscan.io/token/images/usdc_ofc_32.svg", - symbol: "USDC", - }, - { - address: "0xdAC17F958D2ee523a2206206994597C13D831ec7", - decimals: 6, - logo: "https://etherscan.io/token/images/tethernew_32.svg", - symbol: "USDT", - }, - { - address: "0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f", - decimals: 18, - logo: "https://etherscan.io/token/images/aavegho_new_32.png", - symbol: "GHO", - }, - { - address: "0x6B175474E89094C44Da98b954EedeAC495271d0F", + address: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", decimals: 18, - logo: "https://etherscan.io/token/images/dairplce_32.svg", - symbol: "DAI", + logo: "https://bscscan.com/token/images/centre-usdc_28.png", + symbol: "USDC", }, { - address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + address: "0x55d398326f99059fF775485246999027B3197955", decimals: 18, - logo: "https://etherscan.io/token/images/weth_28.png", - symbol: "WETH", + logo: "https://bscscan.com/token/images/busdt_32.png", + symbol: "USDT", }, ], executeDeposit: ( @@ -318,7 +287,7 @@ const OPPORTUNITIES = { chainId: number, user: `0x${string}`, ) => ({ - to: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" as const, + to: "0x6807dc923806fE8Fd134338EABCA509979a7e0cB" as const, gas: BigInt(400_000), data: encodeFunctionData({ abi: AAVE_ABI, @@ -328,22 +297,21 @@ const OPPORTUNITIES = { tokenApproval: { toTokenAddress: tokenAddress, amount, - spender: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" as const, + spender: "0x6807dc923806fE8Fd134338EABCA509979a7e0cB" as const, }, }), }, // 3. Compound on Polygon (USDT) - "compound-pol-usdt": { + "compound-eth-usdt": { protocol: "Compound", depositTargetLogo: "https://files.availproject.org/uploads/2026-04-16/compound.svg", - chainId: 137, + chainId: 1, tokenSymbol: "USDT", - tokenAddress: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F" as const, + tokenAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7" as const, tokenDecimals: 6, - tokenLogo: - "https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdt/logo.png", + tokenLogo: "https://etherscan.io/token/images/tethernew_32.svg", executeDeposit: ( symbol: string, tokenAddress: `0x${string}`, @@ -351,7 +319,7 @@ const OPPORTUNITIES = { chainId: number, user: `0x${string}`, ) => ({ - to: "0xaeB318360f27748Acb200CE616E389A6C9409a07" as const, + to: "0x3Afdc9BCA9213A35503b077a6072F3D0d5AB0840" as const, gas: BigInt(400_000), data: encodeFunctionData({ abi: COMPOUND_ABI, @@ -361,21 +329,20 @@ const OPPORTUNITIES = { tokenApproval: { toTokenAddress: tokenAddress, amount, - spender: "0xaeB318360f27748Acb200CE616E389A6C9409a07" as const, + spender: "0x3Afdc9BCA9213A35503b077a6072F3D0d5AB0840" as const, }, }), }, // 4. Fluid on Base (USDC) - "fluid-base-usdc": { + "fluid-arb-usdc": { protocol: "Fluid", depositTargetLogo: "https://fluid.instad.app/images/logo.png", - chainId: 8453, + chainId: 42161, tokenSymbol: "USDC", - tokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" as const, + tokenAddress: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" as const, tokenDecimals: 6, - tokenLogo: - "https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdc/logo.png", + tokenLogo: "https://arbiscan.io/token/images/centre-usdc_28.png", executeDeposit: ( symbol: string, tokenAddress: `0x${string}`, @@ -383,7 +350,7 @@ const OPPORTUNITIES = { chainId: number, user: `0x${string}`, ) => ({ - to: "0xf42f5795D9ac7e9D757dB633D693cD548Cfd9169" as const, + to: "0x1A996cb54bb95462040408C06122D45D6Cdb6096" as const, gas: BigInt(400_000), data: encodeFunctionData({ abi: FLUID_ABI, @@ -393,13 +360,14 @@ const OPPORTUNITIES = { tokenApproval: { toTokenAddress: tokenAddress, amount, - spender: "0xf42f5795D9ac7e9D757dB633D693cD548Cfd9169" as const, + spender: "0x1A996cb54bb95462040408C06122D45D6Cdb6096" as const, }, }), }, // 5. Mystic on Citrea (ctUSD) "mystic-citrea-ctusd": { + label: "Mystic ctUSD (onramp not supported)", protocol: "Mystic", depositTargetLogo: "https://files.availproject.org/nexus-elements/mystic.png", @@ -432,6 +400,7 @@ const OPPORTUNITIES = { // 6. Zentra on Citrea (wcBTC) "zentra-citrea-wcbtc": { + label: "Zentra wcBTC (onramp not supported)", protocol: "Zentra", depositTargetLogo: "https://zentrafinance.gitbook.io/zentra/~gitbook/image?url=https%3A%2F%2F2899070418-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Forganizations%252F1jzW9aBSq190MuRJKgIj%252Fsites%252Fsite_2l6Ro%252Ficon%252Fb8adwB6RA7Y6VJH3vGjh%252FZentra%2520%284%29.png%3Falt%3Dmedia%26token%3D8aa44578-e817-4c2f-b20e-abd25827d4fe&width=32&dpr=3&quality=100&sign=d18163fe&sv=2", @@ -473,9 +442,9 @@ const NexusWidgetDepositShowcase = () => { >("aave-arbitrum"); const [isOpen, setIsOpen] = useState(false); const [isSandboxModalOpen, setIsSandboxModalOpen] = useState(false); - const [renderMode, setRenderMode] = - useState("inline"); + const [renderMode, setRenderMode] = useState("inline"); const isPopupMode = renderMode === "popup"; + const [enableOnRamp, setEnableOnRamp] = useState(true); // Default sandbox configuration state const [sandboxConfig, setSandboxConfig] = useState<{ @@ -746,10 +715,33 @@ const NexusWidgetDepositShowcase = () => { type="nexus-widget" connectLabel="Connect wallet to use Deposit" controls={ - +
+ + +
} >
@@ -936,7 +928,7 @@ const NexusWidgetDepositShowcase = () => { }} > { }, depositAddress: resolveDepositAddress(currentOpportunity), executeDeposit: currentOpportunity.executeDeposit, + enableOnRamp, appearance: { appLogoURL: currentOpportunity.depositTargetLogo, appName: currentOpportunity.protocol, diff --git a/content/docs/components/deposit.mdx b/content/docs/components/deposit.mdx index b0fa1b0e..ea7cede1 100644 --- a/content/docs/components/deposit.mdx +++ b/content/docs/components/deposit.mdx @@ -147,6 +147,7 @@ const APP_DEPOSIT_ABI = [ const depositConfig = { mode: "deposit", + enableOnRamp: true, // Optional; defaults to false (wallet funding only). destination: { chain: DESTINATION_CHAIN_ID, tokens: [ @@ -206,6 +207,7 @@ Deposit uses only `mode: "deposit"`. This mode is exact-out: users enter the des | `config.destination.tokens` | Yes | One or more accepted destination tokens. The token dropdown is limited to this list and is editable only when multiple tokens are supplied. | | `config.depositAddress` | Yes | Smart contract address for the deposit target. | | `config.executeDeposit` | Yes | Callback builder returning `{ to, gas, data?, value?, tokenApproval? }` for the final app transaction. `gas` must be a positive `bigint`. | +| `config.enableOnRamp` | Optional | Defaults to `false`. Set `true` to display "Deposit with Cash" alongside wallet funding. | | `config.prefill.amount` | Optional | Prefills the exact output deposit amount. Must be greater than `0`. | | `config.validation.minAmount` | Optional | Minimum deposit amount. Must be `0` or greater. | | `config.validation.maxAmount` | Optional | Maximum deposit amount. Must be greater than `0`. | @@ -216,6 +218,8 @@ Deposit uses only `mode: "deposit"`. This mode is exact-out: users enter the des | `open`, `onOpenChange`, `defaultOpen` | Optional | Control the modal when `embed={false}`. | | `onStart`, `onComplete`, `onError`, `onClose`, `onConnectClick`, `onConnectWallet` | Optional | Host app callbacks. Use `onConnectClick` to open your app/header wallet modal from the element CTA. | +Set `enableOnRamp: true` to offer wallet and local currency funding. Set it to `false` or omit it to open directly in the wallet deposit flow. The showcase Onramp toggle demonstrates both settings. + ### `executeDeposit` ```ts @@ -348,6 +352,7 @@ export function MultiDepositShowcase({ address }) { void` | Called after a successful swap, send, or deposit. | | `onStart` | `() => void` | Called when the user starts execution. | | `onError` | `(message: string) => void` | Called when execution fails. | -| `onClose` | `() => void` | Used by modal mode. | +| `onClose` | `() => void` | Optional callback when the popup closes; the close button also works without this callback. | | `onConnectClick` | `() => void \| Promise` | Called when the internal Connect Wallet CTA is clicked. Use this to open your app/header wallet modal. | | `onConnectWallet` | `() => void \| Promise` | Backward-compatible connect callback prop. | @@ -186,7 +186,7 @@ Dark mode uses a plain background. Light mode keeps its existing background grap ### Deposit Config -Deposit requires a fixed destination chain, at least one destination token, a deposit contract address, and an execution builder. +Deposit requires a fixed destination chain, at least one destination token, a deposit contract address, and an execution builder. Set `enableOnRamp: true` to also offer local currency funding; omitting it or setting `false` opens the wallet deposit flow directly. ```ts type NexusWidgetDepositConfig = { @@ -202,6 +202,7 @@ type NexusWidgetDepositConfig = { }[]; }; depositAddress: `0x${string}`; + enableOnRamp?: boolean; // Defaults to false. executeDeposit: ( tokenSymbol: string, tokenAddress: `0x${string}`, @@ -496,6 +497,7 @@ function buildDepositExecuteConfig( const depositConfig = { mode: "deposit", + enableOnRamp: true, // Optional; defaults to false (wallet funding only). destination: { chain: DESTINATION_CHAIN_ID, tokens: [ diff --git a/docs/onramp-troubleshooting.md b/docs/onramp-troubleshooting.md new file mode 100644 index 00000000..79437c65 --- /dev/null +++ b/docs/onramp-troubleshooting.md @@ -0,0 +1,75 @@ +# Onramp + Deposit diagnostics (2.1.0) + +Both package manifests and the shadcn registry pin `@avail-project/nexus-core` to `2.5.0`. + +## Fixed failure paths + +- Next.js needs literal `process.env.NEXT_PUBLIC_…` references to inline browser configuration. The previous dynamic lookup could miss the configured production environment, infer sandbox from the canary proxy URL, and report deposit success when a cached balance was missing or small. The sandbox success shortcut has been removed. Success requires a successful deposit receipt in every environment. +- Both middleware session responses (`sessionId`, `state`, `transaction`) and Meld responses (`transaction.status`, numeric amounts, `cryptoDetails`) are normalized. Provider checkout URLs, quote provider names and route method names support the documented Meld field names too. +- Chain IDs from middleware `transaction.chainId` and Meld `transaction.cryptoDetails.chainId` are normalized before destination checks: `10`, `"10"`, `"0xa"`, and `"EVM_10"` all identify Optimism. A malformed supplied ID rejects the response instead of bypassing the chain check; a valid different chain still blocks the deposit. +- Returned `transaction.destinationAmount`, `sourceAmount`, and `sourceCurrencyCode` override the checkout quote. A returned transaction payment method or provider takes precedence over session defaults. Partial responses retain previously reported values; missing methods do not overwrite the selected method. The original quote is retained for display when the provider omits a field. Deposit execution always requires a received amount from the settled transaction. +- Transaction history includes local **Onramp** entries with provider, token amount, fiat amount/currency, available payment method, and payment status, including pending and failed sessions. Quoted amounts are identified when returned amounts are unavailable. Entries are saved by session ID as soon as the session is created, and scoped to the wallet and middleware URL. Saved data excludes checkout URLs and unrecognized provider fields. +- Saved entries load when the widget mounts. Opening history refreshes pending sessions immediately, then every five seconds after each completed pass. Focus, online and visibility events refresh sooner. Hidden tabs skip requests, closing history aborts pending reads, and terminal payments stop polling. Refresh failures preserve the last known status. An onramp marked **Completed** means the purchase settled; history polling never executes a deposit or signs a transaction. The history button is available on the deposit funding-method screen. +- `SETTLED` means the purchase is complete. It triggers the deposit once the funded wallet is connected; it no longer means the whole flow succeeded. The actual received amount comes from the transaction, not the earlier quote. The wallet balance is checked immediately, then retried every second up to 60 times before showing a retryable insufficient-balance error (RPC response time can extend the wait). Missing amounts surface a deposit error with a retry action. A disconnected wallet gets a Connect Wallet action while retaining the settled purchase. +- A stored `connectedAddress` is only a display hint for onramp. Connection checks use the active wagmi connector's provider, its connection/session state, `eth_accounts`, `eth_chainId`, and the signing client's account. Disconnected or expired WalletConnect sessions cannot enable Pay. Once a preview quote arrives, disconnected users see Connect Wallet. Reconnecting invalidates the quote, including for the same address, and refreshes it for the verified account before enabling Pay. A final provider check runs before session creation and each deposit signing step. +- Wallet checks have an eight-second timeout, listen for provider connection/account/session events, and refresh on focus, visibility, reconnect, and a five-second interval without overlapping checks. Unmount removes listeners/timers and ignores late responses. `[Nexus Onramp]` includes `wallet.connection`, `wallet.connect_requested`, `wallet.disconnected`, and `wallet.check_failed`. These checks cannot keep a wallet connected throughout an external checkout; the settled screen offers reconnection if the session drops. +- Popup widgets (`embed={false}`) ignore outside clicks and Escape. The header close button is present even without an `onClose` callback. Existing restrictions on closing during transaction progress still apply. +- Gas and token balances are read again after checkout. A gas swap deducts its spend from this purchase rather than depositing the wallet's entire balance. The intent is denied if its source spend would consume the purchased amount. +- Deposit and approval transaction hashes are retained during this mounted session. Retrying confirmation checks the submitted transaction instead of blindly submitting another. An on-chain revert permits a new attempt. +- Polling uses a single request at a time, requests uncached responses, has a 20-second HTTP deadline, and refreshes immediately on provider return, window focus, visibility restoration or reconnect. Cleanup removes timers/listeners, aborts requests and prevents subsequent deposit submissions from an abandoned flow. RPC fetches have a 15-second deadline. Receipt polling has a two-minute confirmation window. +- The callback page does not claim payment success. Callback messages only request a fresh status check. The UI now asks users to keep the original page open because the final deposit needs their connected wallet. An SDK gas swap or wallet transaction already submitted can still finish after closing the page. There is no durable background deposit worker or notification service in this repository. + +## Tester capture + +Use the deployed frontend's browser console, enable **Preserve log**, and filter on: + +```text +[Nexus Onramp] +``` + +These logs are always enabled for the onramp component, including production builds. Wallet-funded deposits, sends and ordinary swaps do not call this logger. Logs contain transaction identifiers, wallet addresses and amounts; checkout tokens and URLs are redacted. SDK events are serialized to JSON, including bigint amounts and SDK error context, so console logging does not retain live SDK/client objects. + +Expected sequence: + +1. `flow.mounted`: proxy URL and resolved onramp environment. +2. Country/options/cache, route and quote API requests, responses and selections. +3. `session.create`, `session.created`, `provider.open`. +4. `poll.status`: session and Meld transaction IDs, previous/new state, raw status, transaction hash, received amount, provider update timestamp and elapsed time. `api.response` includes request duration and exposed cache headers. +5. `provider.return` / `poll.wake` followed by another authoritative status request. +6. `deposit.handoff`, `deposit.amount`, wallet/chain checks, `deposit.balance`, `deposit.gas_check`. +7. When gas is needed: `sdk.swapWithExactOut.start`, `sdk.intent`, every emitted `sdk.event`, and the SDK result/error. The SDK performs the gas swap; approval and final deposit currently use the wallet client directly and therefore emit `wallet.*` diagnostics rather than SDK events. +8. Approval check/prompt/hash/receipt, then `wallet.deposit.prompt`, `wallet.deposit.submitted`, receipt polls, and **`deposit.confirmed`** with the final deposit hash. +9. `ui.state` becomes `DEPOSIT_SUCCESS` only after that receipt. `poll.stop` / `flow.cleanup` show cleanup. + +A `deposit.error` preserves error details and any pending deposit hash. If no `deposit.handoff` appears, inspect the last `poll.status`. If the handoff occurs but no deposit hash follows, inspect the balance, gas, SDK and wallet steps. Wallet signature prompts still require the user to approve them. + +## When Meld has not settled + +Meld documents these as temporary: `PENDING CREATED`, `PENDING`, `SETTLING`, `TWO_FA_REQUIRED`, `TWO_FA_PROVIDED`, `ERROR`, and legacy `ACCEPTED`, `AUTHORIZED`, `PARTIALLY_SETTLED`. `ERROR` can recover; it must not stop polling. The tester must complete outstanding verification in the provider window. + +Terminal payment failures are `FAILED`, `DECLINED`, `CANCELLED`, `REFUNDED` and legacy `AUTHORIZATION_EXPIRED`. Only `SETTLED` authorizes the automatic deposit handoff. Receipt of a redirect or an unrelated wallet balance increase does not establish settlement. + +If crypto arrives before `poll.status` changes to `SETTLED`, compare the receipt time of the onramp transaction with `api.response` timestamps and the provider's `updatedAt`. The frontend checks every three seconds after each completed request while mounted, plus wake events; a stalled request can add up to its timeout. Background browser throttling can also delay checks. The logs distinguish request latency from a server repeatedly returning an old status. The middleware must not cache transaction/session responses and must consume Meld's transaction webhooks (or otherwise fetch fresh Meld transaction data). Its implementation and the tester's transaction trace were not supplied, so this change does not establish whether Meld, Mercuryo, Banxa or the proxy caused a particular reporting delay. + +Meld references: [integration and transaction tracking](https://docs.meld.io/docs/stablecoins/white-label-api-integration/whitelabel-api-guide), [transaction statuses](https://docs.meld.io/docs/stablecoins/for-all-products/transaction-statuses). + +## Configuration and verification + +Onramp is opt-in for deposit widgets: set `config.enableOnRamp: true`. The default is `false`, which opens the wallet deposit flow without mounting the onramp component. In the deposit showcase, enable the **Onramp** toggle before running a payment test. + +```dotenv +NEXT_PUBLIC_NEXUS_ONRAMP_BASE_URL=https://nexus-v2.mainnet.avail.so/middleware +NEXT_PUBLIC_NEXUS_ONRAMP_ENV=production +``` + +Rebuild/redeploy after changing public environment variables. A mainnet Nexus hostname does not identify the Meld sandbox. Even an explicitly configured sandbox cannot fake a successful deposit without a receipt. + +```sh +pnpm test:onramp +pnpm exec tsc --noEmit +pnpm build:registry:json +pnpm build:registry +pnpm build:widgets-package +``` + +The regression suite uses mocked Meld/proxy responses and wallet/RPC calls. It does not charge a card, sign a transaction or test provider webhook delivery. For the RC payment test, keep the page open, approve the wallet prompts, and verify the deposit explorer receipt as well as the provider's onramp receipt. Pending purchase status resumes from local history after reload; deposit execution does not resume automatically. A retained session ID can be inspected with the existing `window.setRampSessionId(id)` helper, but always check already-submitted transactions before attempting deposit recovery after a reload. diff --git a/package.json b/package.json index 268e45a8..fbe54055 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "avail-widgets", - "version": "2.0.10", + "version": "2.1.0", "description": "A modern component registry built with Next.js and shadcn/ui for Avail Nexus", "author": "decocereus ", "contributors": [ @@ -18,14 +18,15 @@ "build": "pnpm postinstall && next build", "start": "next start", "lint": "next lint", + "test:onramp": "node --import tsx --test tests/onramp.test.tsx tests/onramp-chain-id.test.ts tests/onramp-history.test.tsx", "build:registry": "shadcn build", "build:registry:json": "npx tsx scripts/build-registry/index.ts", "build:registry:branch": "pnpm build:registry:json -- --base-url availproject/widgets && pnpm build:registry", - "build:widgets-package": "pnpm --filter @avail-project/widgets build", + "build:widgets-package": "node scripts/build-widgets-package.mjs", "postinstall": "fumadocs-mdx" }, "dependencies": { - "@avail-project/nexus-core": "2.4.1", + "@avail-project/nexus-core": "2.5.0", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-collapsible": "^1.1.12", @@ -67,14 +68,17 @@ }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", + "@tailwindcss/cli": "^4.3.3", "@tailwindcss/postcss": "^4.1.11", "@types/node": "^20.19.9", "@types/react": "19.1.2", "@types/react-dom": "19.1.2", + "@types/react-test-renderer": "19.1.0", "buffer": "^6.0.3", "crypto-browserify": "^3.12.1", "eslint": "^9.32.0", "eslint-config-next": "16.2.3", + "react-test-renderer": "19.2.2", "stream-browserify": "^3.0.0", "tailwindcss": "^4.1.11", "ts-node": "^10.9.2", diff --git a/packages/widgets/README.md b/packages/widgets/README.md index da149c3e..a543b071 100644 --- a/packages/widgets/README.md +++ b/packages/widgets/README.md @@ -16,6 +16,7 @@ pnpm add github:availproject/widgets ```tsx import { NexusProvider, NexusWidget } from "@avail-project/widgets"; +import "@avail-project/widgets/styles.css"; export function App() { return ( @@ -33,21 +34,10 @@ namespace is listed in shadcn, install with: npx shadcn@latest add availproject/widgets/nexus ``` -## Theme +## Onramp + Deposit diagnostics -All three modes support `config.theme: "dark" | "light" | "system"`: +For `config.mode: "deposit"`, set `config.enableOnRamp: true` to offer local currency funding. It defaults to `false`, which opens the wallet deposit flow directly. The deposit showcase includes an Onramp toggle for both settings. -```tsx - -``` +Onramp checks the active wallet provider instead of trusting a persisted address. Disconnected users see Connect Wallet after quotes arrive; reconnecting refreshes the quote for the verified account before Pay is enabled. If the wallet disconnects during checkout, reconnect the funded wallet from the settled purchase screen to finish the deposit. Popup widgets (`embed={false}`) dismiss through the header close button, not outside clicks or Escape. -The default is light. System follows live OS preference changes. Dark uses a -plain background; light keeps the background graphic. Primary-color overrides -continue to work in all themes. The legacy `config.appearance.mode` setting is -used when `config.theme` is omitted. Both embedded widgets and modals are supported. +Version `2.1.0` uses Nexus Core `2.5.0`. Filter the browser console by `[Nexus Onramp]` to trace payment status, SDK gas-swap events, wallet approval and the final deposit receipt. Keep the page open and approve the wallet prompts. See [onramp troubleshooting](../../docs/onramp-troubleshooting.md) in the source repository for configuration, failure cases and testing. diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 2b92899f..21a6816e 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/widgets", - "version": "2.0.10", + "version": "2.1.0", "description": "Compiled Avail widgets for React applications.", "author": "shrinathprabhu ", "contributors": [ @@ -14,7 +14,9 @@ }, "license": "UNLICENSED", "type": "module", - "sideEffects": false, + "sideEffects": [ + "./dist/styles.css" + ], "files": [ "dist", "README.md" @@ -26,7 +28,8 @@ ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" - } + }, + "./styles.css": "./dist/styles.css" }, "scripts": { "build": "node ../../scripts/build-widgets-package.mjs", @@ -38,7 +41,7 @@ "registry": "https://registry.npmjs.org/" }, "dependencies": { - "@avail-project/nexus-core": "2.4.1", + "@avail-project/nexus-core": "2.5.0", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-slot": "^1.2.4", "class-variance-authority": "^0.7.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a9bf936..6dbd7c26 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,67 +1,66 @@ -lockfileVersion: '9.0' +lockfileVersion: "9.0" settings: autoInstallPeers: true excludeLinksFromLockfile: false overrides: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 - axios: '>=1.15.0' + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 + axios: ">=1.15.0" importers: - .: dependencies: - '@avail-project/nexus-core': - specifier: 2.4.1 - version: 2.4.1(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@radix-ui/react-accordion': + "@avail-project/nexus-core": + specifier: 2.5.0 + version: 2.5.0(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@radix-ui/react-accordion": specifier: ^1.2.12 version: 1.2.15(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-checkbox': + "@radix-ui/react-checkbox": specifier: ^1.3.3 version: 1.3.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-collapsible': + "@radix-ui/react-collapsible": specifier: ^1.1.12 version: 1.1.15(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-dialog': + "@radix-ui/react-dialog": specifier: ^1.1.15 version: 1.1.18(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-dropdown-menu': + "@radix-ui/react-dropdown-menu": specifier: ^2.1.16 version: 2.1.19(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-label': + "@radix-ui/react-label": specifier: ^2.1.8 version: 2.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-popover': + "@radix-ui/react-popover": specifier: ^1.1.15 version: 1.1.18(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-select': + "@radix-ui/react-select": specifier: ^2.2.6 version: 2.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-separator': + "@radix-ui/react-separator": specifier: ^1.1.8 version: 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-slot': + "@radix-ui/react-slot": specifier: ^1.2.4 version: 1.3.0(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-switch': + "@radix-ui/react-switch": specifier: ^1.2.6 version: 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-tabs': + "@radix-ui/react-tabs": specifier: ^1.1.13 version: 1.1.16(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-toggle': + "@radix-ui/react-toggle": specifier: ^1.1.10 version: 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-toggle-group': + "@radix-ui/react-toggle-group": specifier: ^1.1.11 version: 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-tooltip': + "@radix-ui/react-tooltip": specifier: ^1.2.8 version: 1.2.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@tanstack/react-query': + "@tanstack/react-query": specifier: ^5.90.21 version: 5.101.2(react@19.2.2) class-variance-authority: @@ -72,7 +71,7 @@ importers: version: 2.1.1 connectkit: specifier: ^1.9.1 - version: 1.9.2(@babel/core@7.29.7)(@tanstack/react-query@5.101.2(react@19.2.2))(react-dom@19.2.2(react@19.2.2))(react-is@16.13.1)(react@19.2.2)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)) + version: 1.9.2(@babel/core@7.29.7)(@tanstack/react-query@5.101.2(react@19.2.2))(react-dom@19.2.2(react@19.2.2))(react-is@19.2.8)(react@19.2.2)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)) decimal.js: specifier: ^10.6.0 version: 10.6.0 @@ -131,21 +130,27 @@ importers: specifier: ^3.25.76 version: 3.25.76 devDependencies: - '@eslint/eslintrc': + "@eslint/eslintrc": specifier: ^3.3.1 version: 3.3.5 - '@tailwindcss/postcss': + "@tailwindcss/cli": + specifier: ^4.3.3 + version: 4.3.3 + "@tailwindcss/postcss": specifier: ^4.1.11 version: 4.3.2 - '@types/node': + "@types/node": specifier: ^20.19.9 version: 20.19.43 - '@types/react': + "@types/react": specifier: 19.1.2 version: 19.1.2 - '@types/react-dom': + "@types/react-dom": specifier: 19.1.2 version: 19.1.2(@types/react@19.1.2) + "@types/react-test-renderer": + specifier: 19.1.0 + version: 19.1.0 buffer: specifier: ^6.0.3 version: 6.0.3 @@ -158,6 +163,9 @@ importers: eslint-config-next: specifier: 16.2.3 version: 16.2.3(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + react-test-renderer: + specifier: 19.2.2 + version: 19.2.2(react@19.2.2) stream-browserify: specifier: ^3.0.0 version: 3.0.0 @@ -176,13 +184,13 @@ importers: packages/widgets: dependencies: - '@avail-project/nexus-core': - specifier: 2.4.1 - version: 2.4.1(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@radix-ui/react-dialog': + "@avail-project/nexus-core": + specifier: 2.5.0 + version: 2.5.0(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@radix-ui/react-dialog": specifier: ^1.1.15 version: 1.1.18(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-slot': + "@radix-ui/react-slot": specifier: ^1.2.4 version: 1.3.0(@types/react@19.1.2)(react@19.2.2) class-variance-authority: @@ -198,10 +206,10 @@ importers: specifier: ^0.487.0 version: 0.487.0(react@19.2.2) react: - specifier: '>=18.3.0 || >=19.0.0' + specifier: ">=18.3.0 || >=19.0.0" version: 19.2.2 react-dom: - specifier: '>=18.3.0 || >=19.0.0' + specifier: ">=18.3.0 || >=19.0.0" version: 19.2.2(react@19.2.2) tailwind-merge: specifier: ^3.3.1 @@ -213,10 +221,10 @@ importers: specifier: ^2.17.4 version: 2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(zod@4.4.3) devDependencies: - '@types/react': + "@types/react": specifier: 19.1.2 version: 19.1.2 - '@types/react-dom': + "@types/react-dom": specifier: 19.1.2 version: 19.1.2(@types/react@19.1.2) typescript: @@ -224,23 +232,31 @@ importers: version: 5.9.3 packages: - - '@0no-co/graphql.web@1.3.2': - resolution: {integrity: sha512-Q1+pRlLhE31GOY/2c9BAEnFTNxO7Awtc6fhhEDlxyCBQ2N0IhD32cPVvPChrK9mwBNSgRdW/sF1kd2e0ojHj1Q==} + "@0no-co/graphql.web@1.3.2": + resolution: + { + integrity: sha512-Q1+pRlLhE31GOY/2c9BAEnFTNxO7Awtc6fhhEDlxyCBQ2N0IhD32cPVvPChrK9mwBNSgRdW/sF1kd2e0ojHj1Q==, + } peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 peerDependenciesMeta: graphql: optional: true - '@0no-co/graphqlsp@1.17.3': - resolution: {integrity: sha512-4PPvxDPmbntddpgMyA3VId5/E9YGdRuuS/mW+THOvtTx/C79Pf+lN28LkNNACJrF9L7YACiAJelyOkC6LqUzvw==} + "@0no-co/graphqlsp@1.17.3": + resolution: + { + integrity: sha512-4PPvxDPmbntddpgMyA3VId5/E9YGdRuuS/mW+THOvtTx/C79Pf+lN28LkNNACJrF9L7YACiAJelyOkC6LqUzvw==, + } peerDependencies: graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 typescript: ^5.0.0 || ^6.0.0 - '@aave/account@0.2.0': - resolution: {integrity: sha512-fk9KcC0He0WNvUGytxVv4urh8F+zznm6ZdpgKnNvq9jKUpnc2HSSn7mS3n4h13h80WtF8OL6rpL50ctqqc4/Nw==} + "@aave/account@0.2.0": + resolution: + { + integrity: sha512-fk9KcC0He0WNvUGytxVv4urh8F+zznm6ZdpgKnNvq9jKUpnc2HSSn7mS3n4h13h80WtF8OL6rpL50ctqqc4/Nw==, + } peerDependencies: react: 17.x || 18.x || 19.x react-dom: 17.x || 18.x || 19.x @@ -256,1863 +272,3007 @@ packages: wagmi: optional: true - '@adraffy/ens-normalize@1.11.1': - resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==} - - '@alloc/quick-lru@5.2.0': - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - - '@antfu/ni@23.3.1': - resolution: {integrity: sha512-C90iyzm/jLV7Lomv2UzwWUzRv9WZr1oRsFRKsX5HjQL4EXrbi9H/RtBkjCP+NF+ABZXUKpAa4F1dkoTaea4zHg==} + "@adraffy/ens-normalize@1.11.1": + resolution: + { + integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==, + } + + "@alloc/quick-lru@5.2.0": + resolution: + { + integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==, + } + engines: { node: ">=10" } + + "@antfu/ni@23.3.1": + resolution: + { + integrity: sha512-C90iyzm/jLV7Lomv2UzwWUzRv9WZr1oRsFRKsX5HjQL4EXrbi9H/RtBkjCP+NF+ABZXUKpAa4F1dkoTaea4zHg==, + } hasBin: true - '@avail-project/nexus-core@2.4.1': - resolution: {integrity: sha512-A3XD2RNO9N/PPFVVkMfhLupt9H66zNTpjMWYFnheXA9YgwQDXGtY1kJqo9vqZ7nGOLo9Z4yoyZg54sRccYghZg==} - engines: {node: '>=18.0.0'} - - '@avail-project/nexus-types@0.1.25': - resolution: {integrity: sha512-KDEFVSjfGmCW0tKiNGS/zrB8yl9m8IPt+HBvIlgYk1G4Nh45fxCEfi0vKHyfzdmy7Ya44HNZglf+R/l6YkGM5A==} + "@avail-project/nexus-core@2.5.0": + resolution: + { + integrity: sha512-coj7PVfKk2jDKk3xPYRn7OpY33yFMQOf3e1JQZg/n9fk0wxYbU8gizu/D2qbAbVrHXzgatytSljtNoaWCfHlZg==, + } + engines: { node: ">=18.0.0" } + + "@avail-project/nexus-types@0.1.25": + resolution: + { + integrity: sha512-KDEFVSjfGmCW0tKiNGS/zrB8yl9m8IPt+HBvIlgYk1G4Nh45fxCEfi0vKHyfzdmy7Ya44HNZglf+R/l6YkGM5A==, + } peerDependencies: - zod: '>=4.0.0' - - '@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.7': - resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-annotate-as-pure@7.29.7': - resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} - 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-create-class-features-plugin@7.29.7': - resolution: {integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==} - engines: {node: '>=6.9.0'} + zod: ">=4.0.0" + + "@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.7": + resolution: + { + integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-annotate-as-pure@7.29.7": + resolution: + { + integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==, + } + 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-create-class-features-plugin@7.29.7": + resolution: + { + integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==, + } + engines: { node: ">=6.9.0" } peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-globals@7.29.7': - resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-member-expression-to-functions@7.29.7': - resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==} - 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'} + "@babel/core": ^7.0.0 + + "@babel/helper-globals@7.29.7": + resolution: + { + integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-member-expression-to-functions@7.29.7": + resolution: + { + integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==, + } + 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-optimise-call-expression@7.29.7': - resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==} - engines: {node: '>=6.9.0'} - - '@babel/helper-plugin-utils@7.29.7': - resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-replace-supers@7.29.7': - resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==} - engines: {node: '>=6.9.0'} + "@babel/core": ^7.0.0 + + "@babel/helper-optimise-call-expression@7.29.7": + resolution: + { + integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-plugin-utils@7.29.7": + resolution: + { + integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-replace-supers@7.29.7": + resolution: + { + integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==, + } + engines: { node: ">=6.9.0" } peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-skip-transparent-expression-wrappers@7.29.7': - resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} - 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.7': - resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} - engines: {node: '>=6.0.0'} + "@babel/core": ^7.0.0 + + "@babel/helper-skip-transparent-expression-wrappers@7.29.7": + resolution: + { + integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==, + } + 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.7": + resolution: + { + integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==, + } + engines: { node: ">=6.0.0" } hasBin: true - '@babel/plugin-syntax-jsx@7.29.7': - resolution: {integrity: sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==} - engines: {node: '>=6.9.0'} + "@babel/plugin-syntax-jsx@7.29.7": + resolution: + { + integrity: sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==, + } + engines: { node: ">=6.9.0" } peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-typescript@7.29.7': - resolution: {integrity: sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==} - engines: {node: '>=6.9.0'} + "@babel/core": ^7.0.0-0 + + "@babel/plugin-syntax-typescript@7.29.7": + resolution: + { + integrity: sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==, + } + engines: { node: ">=6.9.0" } peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-typescript@7.29.7': - resolution: {integrity: sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==} - engines: {node: '>=6.9.0'} + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-typescript@7.29.7": + resolution: + { + integrity: sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==, + } + engines: { node: ">=6.9.0" } peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/runtime@7.29.7': - resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} - engines: {node: '>=6.9.0'} - - '@babel/template@7.29.7': - resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.29.7': - resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.29.7': - resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} - engines: {node: '>=6.9.0'} - - '@base-org/account@2.4.0': - resolution: {integrity: sha512-A4Umpi8B9/pqR78D1Yoze4xHyQaujioVRqqO3d6xuDFw9VRtjg6tK3bPlwE0aW+nVH/ntllCpPa2PbI8Rnjcug==} - - '@coinbase/cdp-sdk@1.51.2': - resolution: {integrity: sha512-o4IEwXbyAjfhPQWoFBuqnV1JQGLk4NlUVMzH/ur4voPSjYZvlYFVuOoE/eEcsoPFN28xaWTBvqebwncQL8h8fQ==} - - '@coinbase/wallet-sdk@3.9.3': - resolution: {integrity: sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw==} - - '@coinbase/wallet-sdk@4.3.6': - resolution: {integrity: sha512-4q8BNG1ViL4mSAAvPAtpwlOs1gpC+67eQtgIwNvT3xyeyFFd+guwkc8bcX5rTmQhXpqnhzC4f0obACbP9CqMSA==} - - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - - '@ecies/ciphers@0.2.6': - resolution: {integrity: sha512-patgsRPKGkhhoBjETV4XxD0En4ui5fbX0hzayqI3M8tvNMGUoUvmyYAIWwlxBc1KX5cturfqByYdj5bYGRpN9g==} - engines: {bun: '>=1', deno: '>=2.7.10', node: '>=16'} + "@babel/core": ^7.0.0-0 + + "@babel/runtime@7.29.7": + resolution: + { + integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==, + } + engines: { node: ">=6.9.0" } + + "@babel/template@7.29.7": + resolution: + { + integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==, + } + engines: { node: ">=6.9.0" } + + "@babel/traverse@7.29.7": + resolution: + { + integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==, + } + engines: { node: ">=6.9.0" } + + "@babel/types@7.29.7": + resolution: + { + integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==, + } + engines: { node: ">=6.9.0" } + + "@base-org/account@2.4.0": + resolution: + { + integrity: sha512-A4Umpi8B9/pqR78D1Yoze4xHyQaujioVRqqO3d6xuDFw9VRtjg6tK3bPlwE0aW+nVH/ntllCpPa2PbI8Rnjcug==, + } + + "@coinbase/cdp-sdk@1.51.2": + resolution: + { + integrity: sha512-o4IEwXbyAjfhPQWoFBuqnV1JQGLk4NlUVMzH/ur4voPSjYZvlYFVuOoE/eEcsoPFN28xaWTBvqebwncQL8h8fQ==, + } + + "@coinbase/wallet-sdk@3.9.3": + resolution: + { + integrity: sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw==, + } + + "@coinbase/wallet-sdk@4.3.6": + resolution: + { + integrity: sha512-4q8BNG1ViL4mSAAvPAtpwlOs1gpC+67eQtgIwNvT3xyeyFFd+guwkc8bcX5rTmQhXpqnhzC4f0obACbP9CqMSA==, + } + + "@cspotcode/source-map-support@0.8.1": + resolution: + { + integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==, + } + engines: { node: ">=12" } + + "@ecies/ciphers@0.2.6": + resolution: + { + integrity: sha512-patgsRPKGkhhoBjETV4XxD0En4ui5fbX0hzayqI3M8tvNMGUoUvmyYAIWwlxBc1KX5cturfqByYdj5bYGRpN9g==, + } + engines: { bun: ">=1", deno: ">=2.7.10", node: ">=16" } peerDependencies: - '@noble/ciphers': ^1.0.0 - - '@emnapi/core@1.10.0': - resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - - '@emnapi/runtime@1.10.0': - resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - - '@emnapi/runtime@1.11.1': - resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} - - '@emnapi/wasi-threads@1.2.1': - resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} - - '@emotion/is-prop-valid@0.8.8': - resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} - - '@emotion/is-prop-valid@1.4.0': - resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==} - - '@emotion/memoize@0.7.4': - resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} - - '@emotion/memoize@0.9.0': - resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} - - '@emotion/stylis@0.8.5': - resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} - - '@emotion/unitless@0.7.5': - resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} - engines: {node: '>=18'} + "@noble/ciphers": ^1.0.0 + + "@emnapi/core@1.10.0": + resolution: + { + integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==, + } + + "@emnapi/runtime@1.10.0": + resolution: + { + integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==, + } + + "@emnapi/runtime@1.11.1": + resolution: + { + integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==, + } + + "@emnapi/wasi-threads@1.2.1": + resolution: + { + integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==, + } + + "@emotion/is-prop-valid@0.8.8": + resolution: + { + integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==, + } + + "@emotion/is-prop-valid@1.4.0": + resolution: + { + integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==, + } + + "@emotion/memoize@0.7.4": + resolution: + { + integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==, + } + + "@emotion/memoize@0.9.0": + resolution: + { + integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==, + } + + "@emotion/stylis@0.8.5": + resolution: + { + integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==, + } + + "@emotion/unitless@0.7.5": + resolution: + { + integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==, + } + + "@esbuild/aix-ppc64@0.25.12": + resolution: + { + integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==, + } + engines: { node: ">=18" } cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.28.1': - resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} - engines: {node: '>=18'} + "@esbuild/aix-ppc64@0.28.1": + resolution: + { + integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==, + } + engines: { node: ">=18" } cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} - engines: {node: '>=18'} + "@esbuild/android-arm64@0.25.12": + resolution: + { + integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==, + } + engines: { node: ">=18" } cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.28.1': - resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} - engines: {node: '>=18'} + "@esbuild/android-arm64@0.28.1": + resolution: + { + integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==, + } + engines: { node: ">=18" } cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} - engines: {node: '>=18'} + "@esbuild/android-arm@0.25.12": + resolution: + { + integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==, + } + engines: { node: ">=18" } cpu: [arm] os: [android] - '@esbuild/android-arm@0.28.1': - resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} - engines: {node: '>=18'} + "@esbuild/android-arm@0.28.1": + resolution: + { + integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==, + } + engines: { node: ">=18" } cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} - engines: {node: '>=18'} + "@esbuild/android-x64@0.25.12": + resolution: + { + integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==, + } + engines: { node: ">=18" } cpu: [x64] os: [android] - '@esbuild/android-x64@0.28.1': - resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} - engines: {node: '>=18'} + "@esbuild/android-x64@0.28.1": + resolution: + { + integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==, + } + engines: { node: ">=18" } cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} - engines: {node: '>=18'} + "@esbuild/darwin-arm64@0.25.12": + resolution: + { + integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==, + } + engines: { node: ">=18" } cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.28.1': - resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} - engines: {node: '>=18'} + "@esbuild/darwin-arm64@0.28.1": + resolution: + { + integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==, + } + engines: { node: ">=18" } cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} - engines: {node: '>=18'} + "@esbuild/darwin-x64@0.25.12": + resolution: + { + integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==, + } + engines: { node: ">=18" } cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.28.1': - resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} - engines: {node: '>=18'} + "@esbuild/darwin-x64@0.28.1": + resolution: + { + integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==, + } + engines: { node: ">=18" } cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} - engines: {node: '>=18'} + "@esbuild/freebsd-arm64@0.25.12": + resolution: + { + integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==, + } + engines: { node: ">=18" } cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.28.1': - resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} - engines: {node: '>=18'} + "@esbuild/freebsd-arm64@0.28.1": + resolution: + { + integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==, + } + engines: { node: ">=18" } cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} - engines: {node: '>=18'} + "@esbuild/freebsd-x64@0.25.12": + resolution: + { + integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==, + } + engines: { node: ">=18" } cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.28.1': - resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} - engines: {node: '>=18'} + "@esbuild/freebsd-x64@0.28.1": + resolution: + { + integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==, + } + engines: { node: ">=18" } cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} - engines: {node: '>=18'} + "@esbuild/linux-arm64@0.25.12": + resolution: + { + integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==, + } + engines: { node: ">=18" } cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.28.1': - resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} - engines: {node: '>=18'} + "@esbuild/linux-arm64@0.28.1": + resolution: + { + integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==, + } + engines: { node: ">=18" } cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} + "@esbuild/linux-arm@0.25.12": + resolution: + { + integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==, + } + engines: { node: ">=18" } cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.28.1': - resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} - engines: {node: '>=18'} + "@esbuild/linux-arm@0.28.1": + resolution: + { + integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==, + } + engines: { node: ">=18" } cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} - engines: {node: '>=18'} + "@esbuild/linux-ia32@0.25.12": + resolution: + { + integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==, + } + engines: { node: ">=18" } cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.28.1': - resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} - engines: {node: '>=18'} + "@esbuild/linux-ia32@0.28.1": + resolution: + { + integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==, + } + engines: { node: ">=18" } cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} + "@esbuild/linux-loong64@0.25.12": + resolution: + { + integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==, + } + engines: { node: ">=18" } cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.28.1': - resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} - engines: {node: '>=18'} + "@esbuild/linux-loong64@0.28.1": + resolution: + { + integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==, + } + engines: { node: ">=18" } cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} + "@esbuild/linux-mips64el@0.25.12": + resolution: + { + integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==, + } + engines: { node: ">=18" } cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.28.1': - resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} - engines: {node: '>=18'} + "@esbuild/linux-mips64el@0.28.1": + resolution: + { + integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==, + } + engines: { node: ">=18" } cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} - engines: {node: '>=18'} + "@esbuild/linux-ppc64@0.25.12": + resolution: + { + integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==, + } + engines: { node: ">=18" } cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.28.1': - resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} - engines: {node: '>=18'} + "@esbuild/linux-ppc64@0.28.1": + resolution: + { + integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==, + } + engines: { node: ">=18" } cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} - engines: {node: '>=18'} + "@esbuild/linux-riscv64@0.25.12": + resolution: + { + integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==, + } + engines: { node: ">=18" } cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.28.1': - resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} - engines: {node: '>=18'} + "@esbuild/linux-riscv64@0.28.1": + resolution: + { + integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==, + } + engines: { node: ">=18" } cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} + "@esbuild/linux-s390x@0.25.12": + resolution: + { + integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==, + } + engines: { node: ">=18" } cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.28.1': - resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} - engines: {node: '>=18'} + "@esbuild/linux-s390x@0.28.1": + resolution: + { + integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==, + } + engines: { node: ">=18" } cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} - engines: {node: '>=18'} + "@esbuild/linux-x64@0.25.12": + resolution: + { + integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==, + } + engines: { node: ">=18" } cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.28.1': - resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} - engines: {node: '>=18'} + "@esbuild/linux-x64@0.28.1": + resolution: + { + integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==, + } + engines: { node: ">=18" } cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} + "@esbuild/netbsd-arm64@0.25.12": + resolution: + { + integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==, + } + engines: { node: ">=18" } cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.28.1': - resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} - engines: {node: '>=18'} + "@esbuild/netbsd-arm64@0.28.1": + resolution: + { + integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==, + } + engines: { node: ">=18" } cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} + "@esbuild/netbsd-x64@0.25.12": + resolution: + { + integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==, + } + engines: { node: ">=18" } cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.28.1': - resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} - engines: {node: '>=18'} + "@esbuild/netbsd-x64@0.28.1": + resolution: + { + integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==, + } + engines: { node: ">=18" } cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} - engines: {node: '>=18'} + "@esbuild/openbsd-arm64@0.25.12": + resolution: + { + integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==, + } + engines: { node: ">=18" } cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.28.1': - resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} - engines: {node: '>=18'} + "@esbuild/openbsd-arm64@0.28.1": + resolution: + { + integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==, + } + engines: { node: ">=18" } cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} + "@esbuild/openbsd-x64@0.25.12": + resolution: + { + integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==, + } + engines: { node: ">=18" } cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.28.1': - resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} - engines: {node: '>=18'} + "@esbuild/openbsd-x64@0.28.1": + resolution: + { + integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==, + } + engines: { node: ">=18" } cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} + "@esbuild/openharmony-arm64@0.25.12": + resolution: + { + integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==, + } + engines: { node: ">=18" } cpu: [arm64] os: [openharmony] - '@esbuild/openharmony-arm64@0.28.1': - resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} - engines: {node: '>=18'} + "@esbuild/openharmony-arm64@0.28.1": + resolution: + { + integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==, + } + engines: { node: ">=18" } cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} - engines: {node: '>=18'} + "@esbuild/sunos-x64@0.25.12": + resolution: + { + integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==, + } + engines: { node: ">=18" } cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.28.1': - resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} - engines: {node: '>=18'} + "@esbuild/sunos-x64@0.28.1": + resolution: + { + integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==, + } + engines: { node: ">=18" } cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} - engines: {node: '>=18'} + "@esbuild/win32-arm64@0.25.12": + resolution: + { + integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==, + } + engines: { node: ">=18" } cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.28.1': - resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} - engines: {node: '>=18'} + "@esbuild/win32-arm64@0.28.1": + resolution: + { + integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==, + } + engines: { node: ">=18" } cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} + "@esbuild/win32-ia32@0.25.12": + resolution: + { + integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==, + } + engines: { node: ">=18" } cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.28.1': - resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} - engines: {node: '>=18'} + "@esbuild/win32-ia32@0.28.1": + resolution: + { + integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==, + } + engines: { node: ">=18" } cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} + "@esbuild/win32-x64@0.25.12": + resolution: + { + integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==, + } + engines: { node: ">=18" } cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.28.1': - resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} - engines: {node: '>=18'} + "@esbuild/win32-x64@0.28.1": + resolution: + { + integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==, + } + engines: { node: ">=18" } cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + "@eslint-community/eslint-utils@4.9.1": + resolution: + { + integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.21.2': - resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/config-helpers@0.4.2': - resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.17.0': - resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/eslintrc@3.3.5': - resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.39.4': - resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.7': - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.4.1': - resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@ethereumjs/common@3.2.0': - resolution: {integrity: sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==} - - '@ethereumjs/rlp@4.0.1': - resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} - engines: {node: '>=14'} + "@eslint-community/regexpp@4.12.2": + resolution: + { + integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==, + } + engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } + + "@eslint/config-array@0.21.2": + resolution: + { + integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@eslint/config-helpers@0.4.2": + resolution: + { + integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@eslint/core@0.17.0": + resolution: + { + integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@eslint/eslintrc@3.3.5": + resolution: + { + integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@eslint/js@9.39.4": + resolution: + { + integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@eslint/object-schema@2.1.7": + resolution: + { + integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@eslint/plugin-kit@0.4.1": + resolution: + { + integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@ethereumjs/common@3.2.0": + resolution: + { + integrity: sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==, + } + + "@ethereumjs/rlp@4.0.1": + resolution: + { + integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==, + } + engines: { node: ">=14" } hasBin: true - '@ethereumjs/tx@4.2.0': - resolution: {integrity: sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==} - engines: {node: '>=14'} - - '@ethereumjs/util@8.1.0': - resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} - engines: {node: '>=14'} - - '@floating-ui/core@1.7.5': - resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} - - '@floating-ui/dom@1.7.6': - resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} - - '@floating-ui/react-dom@2.1.8': - resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==} + "@ethereumjs/tx@4.2.0": + resolution: + { + integrity: sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==, + } + engines: { node: ">=14" } + + "@ethereumjs/util@8.1.0": + resolution: + { + integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==, + } + engines: { node: ">=14" } + + "@floating-ui/core@1.7.5": + resolution: + { + integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==, + } + + "@floating-ui/dom@1.7.6": + resolution: + { + integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==, + } + + "@floating-ui/react-dom@2.1.8": + resolution: + { + integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==, + } peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - - '@floating-ui/utils@0.2.11': - resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} - - '@gemini-wallet/core@0.3.2': - resolution: {integrity: sha512-Z4aHi3ECFf5oWYWM3F1rW83GJfB9OvhBYPTmb5q+VyK3uvzvS48lwo+jwh2eOoCRWEuT/crpb9Vwp2QaS5JqgQ==} + react: ">=16.8.0" + react-dom: ">=16.8.0" + + "@floating-ui/utils@0.2.11": + resolution: + { + integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==, + } + + "@gemini-wallet/core@0.3.2": + resolution: + { + integrity: sha512-Z4aHi3ECFf5oWYWM3F1rW83GJfB9OvhBYPTmb5q+VyK3uvzvS48lwo+jwh2eOoCRWEuT/crpb9Vwp2QaS5JqgQ==, + } peerDependencies: - viem: '>=2.0.0' + viem: ">=2.0.0" - '@gql.tada/cli-utils@1.9.2': - resolution: {integrity: sha512-cVNs4v8ewLRYJfyAsaHbiAmd5Hm+zXEMvMhBksH58ZU87d6f8crsp2CQG6QtIqnJJw1q0CBWfWTZepGWNcL3QA==} + "@gql.tada/cli-utils@1.9.2": + resolution: + { + integrity: sha512-cVNs4v8ewLRYJfyAsaHbiAmd5Hm+zXEMvMhBksH58ZU87d6f8crsp2CQG6QtIqnJJw1q0CBWfWTZepGWNcL3QA==, + } peerDependencies: - '@0no-co/graphqlsp': ^1.16.0 - '@gql.tada/svelte-support': 1.0.3 - '@gql.tada/vue-support': 1.0.3 + "@0no-co/graphqlsp": ^1.16.0 + "@gql.tada/svelte-support": 1.0.3 + "@gql.tada/vue-support": 1.0.3 graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 typescript: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: - '@gql.tada/svelte-support': + "@gql.tada/svelte-support": optional: true - '@gql.tada/vue-support': + "@gql.tada/vue-support": optional: true - '@gql.tada/internal@1.2.1': - resolution: {integrity: sha512-1kPMv9KRpD6mfVwtXK+iy43U/gi4bpr4ganfhPLD0TjxpbuVJm7CtZ9wMFdwy3FjLBFN2QhwscNnL7lRPHg4vg==} + "@gql.tada/internal@1.2.1": + resolution: + { + integrity: sha512-1kPMv9KRpD6mfVwtXK+iy43U/gi4bpr4ganfhPLD0TjxpbuVJm7CtZ9wMFdwy3FjLBFN2QhwscNnL7lRPHg4vg==, + } peerDependencies: graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 typescript: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 - '@graphql-typed-document-node/core@3.2.0': - resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + "@graphql-typed-document-node/core@3.2.0": + resolution: + { + integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==, + } peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@hono/node-server@1.19.14': - resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} - engines: {node: '>=18.14.1'} + "@hono/node-server@1.19.14": + resolution: + { + integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==, + } + engines: { node: ">=18.14.1" } peerDependencies: hono: ^4 - '@humanfs/core@0.19.2': - resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.8': - resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} - engines: {node: '>=18.18.0'} - - '@humanfs/types@0.15.0': - resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.4.3': - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} - engines: {node: '>=18.18'} - - '@img/colour@1.1.0': - resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} - engines: {node: '>=18'} - - '@img/sharp-darwin-arm64@0.34.5': - resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@humanfs/core@0.19.2": + resolution: + { + integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==, + } + engines: { node: ">=18.18.0" } + + "@humanfs/node@0.16.8": + resolution: + { + integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==, + } + engines: { node: ">=18.18.0" } + + "@humanfs/types@0.15.0": + resolution: + { + integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==, + } + engines: { node: ">=18.18.0" } + + "@humanwhocodes/module-importer@1.0.1": + resolution: + { + integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==, + } + engines: { node: ">=12.22" } + + "@humanwhocodes/retry@0.4.3": + resolution: + { + integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==, + } + engines: { node: ">=18.18" } + + "@img/colour@1.1.0": + resolution: + { + integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==, + } + engines: { node: ">=18" } + + "@img/sharp-darwin-arm64@0.34.5": + resolution: + { + integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.34.5': - resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-darwin-x64@0.34.5": + resolution: + { + integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [x64] os: [darwin] - '@img/sharp-libvips-darwin-arm64@1.2.4': - resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + "@img/sharp-libvips-darwin-arm64@1.2.4": + resolution: + { + integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==, + } cpu: [arm64] os: [darwin] - '@img/sharp-libvips-darwin-x64@1.2.4': - resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + "@img/sharp-libvips-darwin-x64@1.2.4": + resolution: + { + integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==, + } cpu: [x64] os: [darwin] - '@img/sharp-libvips-linux-arm64@1.2.4': - resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + "@img/sharp-libvips-linux-arm64@1.2.4": + resolution: + { + integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==, + } cpu: [arm64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-arm@1.2.4': - resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + "@img/sharp-libvips-linux-arm@1.2.4": + resolution: + { + integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==, + } cpu: [arm] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-ppc64@1.2.4': - resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + "@img/sharp-libvips-linux-ppc64@1.2.4": + resolution: + { + integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==, + } cpu: [ppc64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-riscv64@1.2.4': - resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + "@img/sharp-libvips-linux-riscv64@1.2.4": + resolution: + { + integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==, + } cpu: [riscv64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-s390x@1.2.4': - resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + "@img/sharp-libvips-linux-s390x@1.2.4": + resolution: + { + integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==, + } cpu: [s390x] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-x64@1.2.4': - resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + "@img/sharp-libvips-linux-x64@1.2.4": + resolution: + { + integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==, + } cpu: [x64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + "@img/sharp-libvips-linuxmusl-arm64@1.2.4": + resolution: + { + integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==, + } cpu: [arm64] os: [linux] libc: [musl] - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + "@img/sharp-libvips-linuxmusl-x64@1.2.4": + resolution: + { + integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==, + } cpu: [x64] os: [linux] libc: [musl] - '@img/sharp-linux-arm64@0.34.5': - resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-linux-arm64@0.34.5": + resolution: + { + integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [arm64] os: [linux] libc: [glibc] - '@img/sharp-linux-arm@0.34.5': - resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-linux-arm@0.34.5": + resolution: + { + integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [arm] os: [linux] libc: [glibc] - '@img/sharp-linux-ppc64@0.34.5': - resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-linux-ppc64@0.34.5": + resolution: + { + integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [ppc64] os: [linux] libc: [glibc] - '@img/sharp-linux-riscv64@0.34.5': - resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-linux-riscv64@0.34.5": + resolution: + { + integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [riscv64] os: [linux] libc: [glibc] - '@img/sharp-linux-s390x@0.34.5': - resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-linux-s390x@0.34.5": + resolution: + { + integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [s390x] os: [linux] libc: [glibc] - '@img/sharp-linux-x64@0.34.5': - resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-linux-x64@0.34.5": + resolution: + { + integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [x64] os: [linux] libc: [glibc] - '@img/sharp-linuxmusl-arm64@0.34.5': - resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-linuxmusl-arm64@0.34.5": + resolution: + { + integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [arm64] os: [linux] libc: [musl] - '@img/sharp-linuxmusl-x64@0.34.5': - resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-linuxmusl-x64@0.34.5": + resolution: + { + integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [x64] os: [linux] libc: [musl] - '@img/sharp-wasm32@0.34.5': - resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-wasm32@0.34.5": + resolution: + { + integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [wasm32] - '@img/sharp-win32-arm64@0.34.5': - resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-win32-arm64@0.34.5": + resolution: + { + integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [arm64] os: [win32] - '@img/sharp-win32-ia32@0.34.5': - resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-win32-ia32@0.34.5": + resolution: + { + integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.34.5': - resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + "@img/sharp-win32-x64@0.34.5": + resolution: + { + integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } cpu: [x64] os: [win32] - '@inquirer/ansi@2.0.7': - resolution: {integrity: sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - - '@inquirer/confirm@6.1.1': - resolution: {integrity: sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + "@inquirer/ansi@2.0.7": + resolution: + { + integrity: sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==, + } + engines: { node: ">=23.5.0 || ^22.13.0 || ^20.17.0" } + + "@inquirer/confirm@6.1.1": + resolution: + { + integrity: sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==, + } + engines: { node: ">=23.5.0 || ^22.13.0 || ^20.17.0" } peerDependencies: - '@types/node': '>=18' + "@types/node": ">=18" peerDependenciesMeta: - '@types/node': + "@types/node": optional: true - '@inquirer/core@11.2.1': - resolution: {integrity: sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + "@inquirer/core@11.2.1": + resolution: + { + integrity: sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==, + } + engines: { node: ">=23.5.0 || ^22.13.0 || ^20.17.0" } peerDependencies: - '@types/node': '>=18' + "@types/node": ">=18" peerDependenciesMeta: - '@types/node': + "@types/node": optional: true - '@inquirer/figures@2.0.7': - resolution: {integrity: sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - - '@inquirer/type@4.0.7': - resolution: {integrity: sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==} - engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + "@inquirer/figures@2.0.7": + resolution: + { + integrity: sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==, + } + engines: { node: ">=23.5.0 || ^22.13.0 || ^20.17.0" } + + "@inquirer/type@4.0.7": + resolution: + { + integrity: sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==, + } + engines: { node: ">=23.5.0 || ^22.13.0 || ^20.17.0" } peerDependencies: - '@types/node': '>=18' + "@types/node": ">=18" peerDependenciesMeta: - '@types/node': + "@types/node": optional: true - '@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==} - - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - - '@lit-labs/ssr-dom-shim@1.6.0': - resolution: {integrity: sha512-VHb0ALPMTlgKjM6yIxxoQNnpKyUKLD04VzeQdsiXkMqkvYlAHxq9glGLmgbb889/1GsohSOAjvQYoiBppXFqrQ==} - - '@lit/reactive-element@2.1.2': - resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} - - '@mayanfinance/swap-sdk@13.3.0': - resolution: {integrity: sha512-wBsyJB4tTsVEdBeebBykK9KUiLziQ4hLnXomqB8/JT8MjWTCpN50gimAXK/TrepcHkZznQlMarqNNmbGCL9TZw==} - - '@mdx-js/mdx@3.1.1': - resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} - - '@metamask/eth-json-rpc-provider@1.0.1': - resolution: {integrity: sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==} - engines: {node: '>=14.0.0'} - - '@metamask/json-rpc-engine@7.3.3': - resolution: {integrity: sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg==} - engines: {node: '>=16.0.0'} - - '@metamask/json-rpc-engine@8.0.2': - resolution: {integrity: sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA==} - engines: {node: '>=16.0.0'} - - '@metamask/json-rpc-middleware-stream@7.0.2': - resolution: {integrity: sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg==} - engines: {node: '>=16.0.0'} - - '@metamask/object-multiplex@2.1.0': - resolution: {integrity: sha512-4vKIiv0DQxljcXwfpnbsXcfa5glMj5Zg9mqn4xpIWqkv6uJ2ma5/GtUfLFSxhlxnR8asRMv8dDmWya1Tc1sDFA==} - engines: {node: ^16.20 || ^18.16 || >=20} - - '@metamask/onboarding@1.0.1': - resolution: {integrity: sha512-FqHhAsCI+Vacx2qa5mAFcWNSrTcVGMNjzxVgaX8ECSny/BJ9/vgXP9V7WF/8vb9DltPeQkxr+Fnfmm6GHfmdTQ==} - - '@metamask/providers@16.1.0': - resolution: {integrity: sha512-znVCvux30+3SaUwcUGaSf+pUckzT5ukPRpcBmy+muBLC0yaWnBcvDqGfcsw6CBIenUdFrVoAFa8B6jsuCY/a+g==} - engines: {node: ^18.18 || >=20} - - '@metamask/rpc-errors@6.4.0': - resolution: {integrity: sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==} - engines: {node: '>=16.0.0'} - - '@metamask/rpc-errors@7.0.2': - resolution: {integrity: sha512-YYYHsVYd46XwY2QZzpGeU4PSdRhHdxnzkB8piWGvJW2xbikZ3R+epAYEL4q/K8bh9JPTucsUdwRFnACor1aOYw==} - engines: {node: ^18.20 || ^20.17 || >=22} - - '@metamask/safe-event-emitter@2.0.0': - resolution: {integrity: sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==} - - '@metamask/safe-event-emitter@3.1.2': - resolution: {integrity: sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==} - engines: {node: '>=12.0.0'} - - '@metamask/sdk-analytics@0.0.5': - resolution: {integrity: sha512-fDah+keS1RjSUlC8GmYXvx6Y26s3Ax1U9hGpWb6GSY5SAdmTSIqp2CvYy6yW0WgLhnYhW+6xERuD0eVqV63QIQ==} + "@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==, + } + + "@jridgewell/trace-mapping@0.3.9": + resolution: + { + integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, + } + + "@lit-labs/ssr-dom-shim@1.6.0": + resolution: + { + integrity: sha512-VHb0ALPMTlgKjM6yIxxoQNnpKyUKLD04VzeQdsiXkMqkvYlAHxq9glGLmgbb889/1GsohSOAjvQYoiBppXFqrQ==, + } + + "@lit/reactive-element@2.1.2": + resolution: + { + integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==, + } + + "@mayanfinance/swap-sdk@13.3.0": + resolution: + { + integrity: sha512-wBsyJB4tTsVEdBeebBykK9KUiLziQ4hLnXomqB8/JT8MjWTCpN50gimAXK/TrepcHkZznQlMarqNNmbGCL9TZw==, + } + + "@mdx-js/mdx@3.1.1": + resolution: + { + integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==, + } + + "@metamask/eth-json-rpc-provider@1.0.1": + resolution: + { + integrity: sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==, + } + engines: { node: ">=14.0.0" } + + "@metamask/json-rpc-engine@7.3.3": + resolution: + { + integrity: sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg==, + } + engines: { node: ">=16.0.0" } + + "@metamask/json-rpc-engine@8.0.2": + resolution: + { + integrity: sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA==, + } + engines: { node: ">=16.0.0" } + + "@metamask/json-rpc-middleware-stream@7.0.2": + resolution: + { + integrity: sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg==, + } + engines: { node: ">=16.0.0" } + + "@metamask/object-multiplex@2.1.0": + resolution: + { + integrity: sha512-4vKIiv0DQxljcXwfpnbsXcfa5glMj5Zg9mqn4xpIWqkv6uJ2ma5/GtUfLFSxhlxnR8asRMv8dDmWya1Tc1sDFA==, + } + engines: { node: ^16.20 || ^18.16 || >=20 } + + "@metamask/onboarding@1.0.1": + resolution: + { + integrity: sha512-FqHhAsCI+Vacx2qa5mAFcWNSrTcVGMNjzxVgaX8ECSny/BJ9/vgXP9V7WF/8vb9DltPeQkxr+Fnfmm6GHfmdTQ==, + } + + "@metamask/providers@16.1.0": + resolution: + { + integrity: sha512-znVCvux30+3SaUwcUGaSf+pUckzT5ukPRpcBmy+muBLC0yaWnBcvDqGfcsw6CBIenUdFrVoAFa8B6jsuCY/a+g==, + } + engines: { node: ^18.18 || >=20 } + + "@metamask/rpc-errors@6.4.0": + resolution: + { + integrity: sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==, + } + engines: { node: ">=16.0.0" } + + "@metamask/rpc-errors@7.0.2": + resolution: + { + integrity: sha512-YYYHsVYd46XwY2QZzpGeU4PSdRhHdxnzkB8piWGvJW2xbikZ3R+epAYEL4q/K8bh9JPTucsUdwRFnACor1aOYw==, + } + engines: { node: ^18.20 || ^20.17 || >=22 } + + "@metamask/safe-event-emitter@2.0.0": + resolution: + { + integrity: sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==, + } + + "@metamask/safe-event-emitter@3.1.2": + resolution: + { + integrity: sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==, + } + engines: { node: ">=12.0.0" } + + "@metamask/sdk-analytics@0.0.5": + resolution: + { + integrity: sha512-fDah+keS1RjSUlC8GmYXvx6Y26s3Ax1U9hGpWb6GSY5SAdmTSIqp2CvYy6yW0WgLhnYhW+6xERuD0eVqV63QIQ==, + } deprecated: No longer maintained, superseded by @metamask/connect-analytics - '@metamask/sdk-communication-layer@0.33.1': - resolution: {integrity: sha512-0bI9hkysxcfbZ/lk0T2+aKVo1j0ynQVTuB3sJ5ssPWlz+Z3VwveCkP1O7EVu1tsVVCb0YV5WxK9zmURu2FIiaA==} + "@metamask/sdk-communication-layer@0.33.1": + resolution: + { + integrity: sha512-0bI9hkysxcfbZ/lk0T2+aKVo1j0ynQVTuB3sJ5ssPWlz+Z3VwveCkP1O7EVu1tsVVCb0YV5WxK9zmURu2FIiaA==, + } deprecated: No longer maintained, superseded by https://docs.metamask.io/metamask-connect peerDependencies: cross-fetch: ^4.0.0 - eciesjs: '*' + eciesjs: "*" eventemitter2: ^6.4.9 readable-stream: ^3.6.2 socket.io-client: ^4.5.1 - '@metamask/sdk-install-modal-web@0.32.1': - resolution: {integrity: sha512-MGmAo6qSjf1tuYXhCu2EZLftq+DSt5Z7fsIKr2P+lDgdTPWgLfZB1tJKzNcwKKOdf6q9Qmmxn7lJuI/gq5LrKw==} + "@metamask/sdk-install-modal-web@0.32.1": + resolution: + { + integrity: sha512-MGmAo6qSjf1tuYXhCu2EZLftq+DSt5Z7fsIKr2P+lDgdTPWgLfZB1tJKzNcwKKOdf6q9Qmmxn7lJuI/gq5LrKw==, + } deprecated: No longer maintained, superseded by https://docs.metamask.io/metamask-connect - '@metamask/sdk@0.33.1': - resolution: {integrity: sha512-1mcOQVGr9rSrVcbKPNVzbZ8eCl1K0FATsYH3WJ/MH4WcZDWGECWrXJPNMZoEAkLxWiMe8jOQBumg2pmcDa9zpQ==} + "@metamask/sdk@0.33.1": + resolution: + { + integrity: sha512-1mcOQVGr9rSrVcbKPNVzbZ8eCl1K0FATsYH3WJ/MH4WcZDWGECWrXJPNMZoEAkLxWiMe8jOQBumg2pmcDa9zpQ==, + } deprecated: No longer maintained, superseded by https://docs.metamask.io/metamask-connect - '@metamask/superstruct@3.3.0': - resolution: {integrity: sha512-P/MwKoAIHGgMz7gnfIV9jP0wG8f/bCHooy5LPfYWzoyV9FrcHB/9Ai/spIOa6jRmoSr+R6etWvulTakDfwCbrA==} - engines: {node: '>=16.0.0'} - - '@metamask/utils@11.11.0': - resolution: {integrity: sha512-0nF2CWjWQr/m0Y2t2lJnBTU1/CZPPTvKvcESLplyWe/tyeb8zFOi/FeneDmaFnML6LYRIGZU6f+xR0jKAIUZfw==} - engines: {node: ^18.18 || ^20.14 || >=22} - - '@metamask/utils@5.0.2': - resolution: {integrity: sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==} - engines: {node: '>=14.0.0'} - - '@metamask/utils@8.5.0': - resolution: {integrity: sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==} - engines: {node: '>=16.0.0'} - - '@metamask/utils@9.3.0': - resolution: {integrity: sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==} - engines: {node: '>=16.0.0'} - - '@modelcontextprotocol/sdk@1.29.0': - resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} - engines: {node: '>=18'} + "@metamask/superstruct@3.3.0": + resolution: + { + integrity: sha512-P/MwKoAIHGgMz7gnfIV9jP0wG8f/bCHooy5LPfYWzoyV9FrcHB/9Ai/spIOa6jRmoSr+R6etWvulTakDfwCbrA==, + } + engines: { node: ">=16.0.0" } + + "@metamask/utils@11.11.0": + resolution: + { + integrity: sha512-0nF2CWjWQr/m0Y2t2lJnBTU1/CZPPTvKvcESLplyWe/tyeb8zFOi/FeneDmaFnML6LYRIGZU6f+xR0jKAIUZfw==, + } + engines: { node: ^18.18 || ^20.14 || >=22 } + + "@metamask/utils@5.0.2": + resolution: + { + integrity: sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==, + } + engines: { node: ">=14.0.0" } + + "@metamask/utils@8.5.0": + resolution: + { + integrity: sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==, + } + engines: { node: ">=16.0.0" } + + "@metamask/utils@9.3.0": + resolution: + { + integrity: sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==, + } + engines: { node: ">=16.0.0" } + + "@modelcontextprotocol/sdk@1.29.0": + resolution: + { + integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==, + } + engines: { node: ">=18" } peerDependencies: - '@cfworker/json-schema': ^4.1.1 + "@cfworker/json-schema": ^4.1.1 zod: ^3.25 || ^4.0 peerDependenciesMeta: - '@cfworker/json-schema': + "@cfworker/json-schema": optional: true - '@motionone/animation@10.18.0': - resolution: {integrity: sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==} - - '@motionone/dom@10.12.0': - resolution: {integrity: sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==} - - '@motionone/easing@10.18.0': - resolution: {integrity: sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==} - - '@motionone/generators@10.18.0': - resolution: {integrity: sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==} - - '@motionone/types@10.17.1': - resolution: {integrity: sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==} - - '@motionone/utils@10.18.0': - resolution: {integrity: sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==} - - '@mswjs/interceptors@0.41.9': - resolution: {integrity: sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==} - engines: {node: '>=18'} - - '@mysten/bcs@1.9.2': - resolution: {integrity: sha512-kBk5xrxV9OWR7i+JhL/plQrgQ2/KJhB2pB5gj+w6GXhbMQwS3DPpOvi/zN0Tj84jwPvHMllpEl0QHj6ywN7/eQ==} - - '@mysten/sui@1.45.2': - resolution: {integrity: sha512-gftf7fNpFSiXyfXpbtP2afVEnhc7p2m/MEYc/SO5pov92dacGKOpQIF7etZsGDI1Wvhv+dpph+ulRNpnYSs7Bg==} - engines: {node: '>=18'} - - '@mysten/utils@0.2.0': - resolution: {integrity: sha512-CM6kJcJHX365cK6aXfFRLBiuyXc5WSBHQ43t94jqlCAIRw8umgNcTb5EnEA9n31wPAQgLDGgbG/rCUISCTJ66w==} - - '@napi-rs/wasm-runtime@1.1.6': - resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + "@motionone/animation@10.18.0": + resolution: + { + integrity: sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==, + } + + "@motionone/dom@10.12.0": + resolution: + { + integrity: sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==, + } + + "@motionone/easing@10.18.0": + resolution: + { + integrity: sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==, + } + + "@motionone/generators@10.18.0": + resolution: + { + integrity: sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==, + } + + "@motionone/types@10.17.1": + resolution: + { + integrity: sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==, + } + + "@motionone/utils@10.18.0": + resolution: + { + integrity: sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==, + } + + "@mswjs/interceptors@0.41.9": + resolution: + { + integrity: sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==, + } + engines: { node: ">=18" } + + "@mysten/bcs@1.9.2": + resolution: + { + integrity: sha512-kBk5xrxV9OWR7i+JhL/plQrgQ2/KJhB2pB5gj+w6GXhbMQwS3DPpOvi/zN0Tj84jwPvHMllpEl0QHj6ywN7/eQ==, + } + + "@mysten/sui@1.45.2": + resolution: + { + integrity: sha512-gftf7fNpFSiXyfXpbtP2afVEnhc7p2m/MEYc/SO5pov92dacGKOpQIF7etZsGDI1Wvhv+dpph+ulRNpnYSs7Bg==, + } + engines: { node: ">=18" } + + "@mysten/utils@0.2.0": + resolution: + { + integrity: sha512-CM6kJcJHX365cK6aXfFRLBiuyXc5WSBHQ43t94jqlCAIRw8umgNcTb5EnEA9n31wPAQgLDGgbG/rCUISCTJ66w==, + } + + "@napi-rs/wasm-runtime@1.1.6": + resolution: + { + integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==, + } peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 - - '@next/env@16.2.3': - resolution: {integrity: sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA==} - - '@next/eslint-plugin-next@16.2.3': - resolution: {integrity: sha512-nE/b9mht28XJxjTwKs/yk7w4XTaU3t40UHVAky6cjiijdP/SEy3hGsnQMPxmXPTpC7W4/97okm6fngKnvCqVaA==} - - '@next/swc-darwin-arm64@16.2.3': - resolution: {integrity: sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg==} - engines: {node: '>= 10'} + "@emnapi/core": ^1.7.1 + "@emnapi/runtime": ^1.7.1 + + "@next/env@16.2.3": + resolution: + { + integrity: sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA==, + } + + "@next/eslint-plugin-next@16.2.3": + resolution: + { + integrity: sha512-nE/b9mht28XJxjTwKs/yk7w4XTaU3t40UHVAky6cjiijdP/SEy3hGsnQMPxmXPTpC7W4/97okm6fngKnvCqVaA==, + } + + "@next/swc-darwin-arm64@16.2.3": + resolution: + { + integrity: sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg==, + } + engines: { node: ">= 10" } cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@16.2.3': - resolution: {integrity: sha512-gHjL/qy6Q6CG3176FWbAKyKh9IfntKZTB3RY/YOJdDFpHGsUDXVH38U4mMNpHVGXmeYW4wj22dMp1lTfmu/bTQ==} - engines: {node: '>= 10'} + "@next/swc-darwin-x64@16.2.3": + resolution: + { + integrity: sha512-gHjL/qy6Q6CG3176FWbAKyKh9IfntKZTB3RY/YOJdDFpHGsUDXVH38U4mMNpHVGXmeYW4wj22dMp1lTfmu/bTQ==, + } + engines: { node: ">= 10" } cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@16.2.3': - resolution: {integrity: sha512-U6vtblPtU/P14Y/b/n9ZY0GOxbbIhTFuaFR7F4/uMBidCi2nSdaOFhA0Go81L61Zd6527+yvuX44T4ksnf8T+Q==} - engines: {node: '>= 10'} + "@next/swc-linux-arm64-gnu@16.2.3": + resolution: + { + integrity: sha512-U6vtblPtU/P14Y/b/n9ZY0GOxbbIhTFuaFR7F4/uMBidCi2nSdaOFhA0Go81L61Zd6527+yvuX44T4ksnf8T+Q==, + } + engines: { node: ">= 10" } cpu: [arm64] os: [linux] libc: [glibc] - '@next/swc-linux-arm64-musl@16.2.3': - resolution: {integrity: sha512-/YV0LgjHUmfhQpn9bVoGc4x4nan64pkhWR5wyEV8yCOfwwrH630KpvRg86olQHTwHIn1z59uh6JwKvHq1h4QEw==} - engines: {node: '>= 10'} + "@next/swc-linux-arm64-musl@16.2.3": + resolution: + { + integrity: sha512-/YV0LgjHUmfhQpn9bVoGc4x4nan64pkhWR5wyEV8yCOfwwrH630KpvRg86olQHTwHIn1z59uh6JwKvHq1h4QEw==, + } + engines: { node: ">= 10" } cpu: [arm64] os: [linux] libc: [musl] - '@next/swc-linux-x64-gnu@16.2.3': - resolution: {integrity: sha512-/HiWEcp+WMZ7VajuiMEFGZ6cg0+aYZPqCJD3YJEfpVWQsKYSjXQG06vJP6F1rdA03COD9Fef4aODs3YxKx+RDQ==} - engines: {node: '>= 10'} + "@next/swc-linux-x64-gnu@16.2.3": + resolution: + { + integrity: sha512-/HiWEcp+WMZ7VajuiMEFGZ6cg0+aYZPqCJD3YJEfpVWQsKYSjXQG06vJP6F1rdA03COD9Fef4aODs3YxKx+RDQ==, + } + engines: { node: ">= 10" } cpu: [x64] os: [linux] libc: [glibc] - '@next/swc-linux-x64-musl@16.2.3': - resolution: {integrity: sha512-Kt44hGJfZSefebhk/7nIdivoDr3Ugp5+oNz9VvF3GUtfxutucUIHfIO0ZYO8QlOPDQloUVQn4NVC/9JvHRk9hw==} - engines: {node: '>= 10'} + "@next/swc-linux-x64-musl@16.2.3": + resolution: + { + integrity: sha512-Kt44hGJfZSefebhk/7nIdivoDr3Ugp5+oNz9VvF3GUtfxutucUIHfIO0ZYO8QlOPDQloUVQn4NVC/9JvHRk9hw==, + } + engines: { node: ">= 10" } cpu: [x64] os: [linux] libc: [musl] - '@next/swc-win32-arm64-msvc@16.2.3': - resolution: {integrity: sha512-O2NZ9ie3Tq6xj5Z5CSwBT3+aWAMW2PIZ4egUi9MaWLkwaehgtB7YZjPm+UpcNpKOme0IQuqDcor7BsW6QBiQBw==} - engines: {node: '>= 10'} + "@next/swc-win32-arm64-msvc@16.2.3": + resolution: + { + integrity: sha512-O2NZ9ie3Tq6xj5Z5CSwBT3+aWAMW2PIZ4egUi9MaWLkwaehgtB7YZjPm+UpcNpKOme0IQuqDcor7BsW6QBiQBw==, + } + engines: { node: ">= 10" } cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@16.2.3': - resolution: {integrity: sha512-Ibm29/GgB/ab5n7XKqlStkm54qqZE8v2FnijUPBgrd67FWrac45o/RsNlaOWjme/B5UqeWt/8KM4aWBwA1D2Kw==} - engines: {node: '>= 10'} + "@next/swc-win32-x64-msvc@16.2.3": + resolution: + { + integrity: sha512-Ibm29/GgB/ab5n7XKqlStkm54qqZE8v2FnijUPBgrd67FWrac45o/RsNlaOWjme/B5UqeWt/8KM4aWBwA1D2Kw==, + } + engines: { node: ">= 10" } cpu: [x64] os: [win32] - '@noble/ciphers@1.2.1': - resolution: {integrity: sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==} - engines: {node: ^14.21.3 || >=16} - - '@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.4.2': - resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} - - '@noble/curves@1.8.0': - resolution: {integrity: sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==} - engines: {node: ^14.21.3 || >=16} - - '@noble/curves@1.8.1': - resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} - 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.4': - resolution: {integrity: sha512-2bKONnuM53lINoDrSmK8qP8W271ms7pygDhZt4SiLOoLwBtoHqeCFi6RG42V8zd3mLHuJFhU/Bmaqo4nX0/kBw==} - 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.7.0': - resolution: {integrity: sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==} - engines: {node: ^14.21.3 || >=16} - - '@noble/hashes@1.7.1': - resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} - 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} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@nolyfill/is-core-module@1.0.39': - resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} - engines: {node: '>=12.4.0'} - - '@open-draft/deferred-promise@2.2.0': - resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} - - '@open-draft/deferred-promise@3.0.0': - resolution: {integrity: sha512-XW375UK8/9SqUVNVa6M0yEy8+iTi4QN5VZ7aZuRFQmy76LRwI9wy5F4YIBU6T+eTe2/DNDo8tqu8RHlwLHM6RA==} - - '@open-draft/logger@0.3.0': - resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} - - '@open-draft/until@2.1.0': - resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - - '@opentelemetry/api-logs@0.219.0': - resolution: {integrity: sha512-FFx7YnaYJlIjqWW/AG/yAZ0L/NEY724PipXXXQLdtZPbLwBGbUMTGL1i/esI56TWfTUXxhLfpgrnWJCG8aUJyg==} - engines: {node: '>=8.0.0'} - - '@opentelemetry/api@1.9.1': - resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} - engines: {node: '>=8.0.0'} - - '@opentelemetry/core@2.8.0': - resolution: {integrity: sha512-hd1Lfh8p545nNz+jq1Ejfz+Mn1hyLuxYn1YzTfFNrxr8urEWMNQLPf1Th8kjOH+HxwawCrtgBp8JpBUR4ZSgww==} - engines: {node: ^18.19.0 || >=20.6.0} + "@noble/ciphers@1.2.1": + resolution: + { + integrity: sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==, + } + engines: { node: ^14.21.3 || >=16 } + + "@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.4.2": + resolution: + { + integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==, + } + + "@noble/curves@1.8.0": + resolution: + { + integrity: sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==, + } + engines: { node: ^14.21.3 || >=16 } + + "@noble/curves@1.8.1": + resolution: + { + integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==, + } + 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.4": + resolution: + { + integrity: sha512-2bKONnuM53lINoDrSmK8qP8W271ms7pygDhZt4SiLOoLwBtoHqeCFi6RG42V8zd3mLHuJFhU/Bmaqo4nX0/kBw==, + } + 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.7.0": + resolution: + { + integrity: sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==, + } + engines: { node: ^14.21.3 || >=16 } + + "@noble/hashes@1.7.1": + resolution: + { + integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==, + } + 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 } + + "@nodelib/fs.scandir@2.1.5": + resolution: + { + integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, + } + engines: { node: ">= 8" } + + "@nodelib/fs.stat@2.0.5": + resolution: + { + integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, + } + engines: { node: ">= 8" } + + "@nodelib/fs.walk@1.2.8": + resolution: + { + integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, + } + engines: { node: ">= 8" } + + "@nolyfill/is-core-module@1.0.39": + resolution: + { + integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==, + } + engines: { node: ">=12.4.0" } + + "@open-draft/deferred-promise@2.2.0": + resolution: + { + integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==, + } + + "@open-draft/deferred-promise@3.0.0": + resolution: + { + integrity: sha512-XW375UK8/9SqUVNVa6M0yEy8+iTi4QN5VZ7aZuRFQmy76LRwI9wy5F4YIBU6T+eTe2/DNDo8tqu8RHlwLHM6RA==, + } + + "@open-draft/logger@0.3.0": + resolution: + { + integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==, + } + + "@open-draft/until@2.1.0": + resolution: + { + integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==, + } + + "@opentelemetry/api-logs@0.219.0": + resolution: + { + integrity: sha512-FFx7YnaYJlIjqWW/AG/yAZ0L/NEY724PipXXXQLdtZPbLwBGbUMTGL1i/esI56TWfTUXxhLfpgrnWJCG8aUJyg==, + } + engines: { node: ">=8.0.0" } + + "@opentelemetry/api@1.9.1": + resolution: + { + integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==, + } + engines: { node: ">=8.0.0" } + + "@opentelemetry/core@2.8.0": + resolution: + { + integrity: sha512-hd1Lfh8p545nNz+jq1Ejfz+Mn1hyLuxYn1YzTfFNrxr8urEWMNQLPf1Th8kjOH+HxwawCrtgBp8JpBUR4ZSgww==, + } + engines: { node: ^18.19.0 || >=20.6.0 } peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - - '@opentelemetry/exporter-logs-otlp-http@0.219.0': - resolution: {integrity: sha512-mhl2HL6GmZI8b8PwPfqMws/5ovJfbRTxwc9Y5agVVHiQ+e5SL1btsFr/kJDgt7YCexDtsUn5HAreHQO9szFS0A==} - engines: {node: ^18.19.0 || >=20.6.0} + "@opentelemetry/api": ">=1.0.0 <1.10.0" + + "@opentelemetry/exporter-logs-otlp-http@0.219.0": + resolution: + { + integrity: sha512-mhl2HL6GmZI8b8PwPfqMws/5ovJfbRTxwc9Y5agVVHiQ+e5SL1btsFr/kJDgt7YCexDtsUn5HAreHQO9szFS0A==, + } + engines: { node: ^18.19.0 || >=20.6.0 } peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/otlp-exporter-base@0.219.0': - resolution: {integrity: sha512-zvIxQX/AZUVKDU+hCuYx+7UkiP7GRdnk1ZbFQRYzHvYp47cAWR4j3IhoPhV9KaeXEv2xdGq3IA6PnpzDmLcmSA==} - engines: {node: ^18.19.0 || >=20.6.0} + "@opentelemetry/api": ^1.3.0 + + "@opentelemetry/otlp-exporter-base@0.219.0": + resolution: + { + integrity: sha512-zvIxQX/AZUVKDU+hCuYx+7UkiP7GRdnk1ZbFQRYzHvYp47cAWR4j3IhoPhV9KaeXEv2xdGq3IA6PnpzDmLcmSA==, + } + engines: { node: ^18.19.0 || >=20.6.0 } peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/otlp-transformer@0.219.0': - resolution: {integrity: sha512-aaYKAyXhw9VchKZVGOopD3Gw/kPsyrX2c6IQ0AW32mTjqmZOh5Y6Gf5OYqTNqVktAeBjmFinhyFaCwW6GYK9YQ==} - engines: {node: ^18.19.0 || >=20.6.0} + "@opentelemetry/api": ^1.3.0 + + "@opentelemetry/otlp-transformer@0.219.0": + resolution: + { + integrity: sha512-aaYKAyXhw9VchKZVGOopD3Gw/kPsyrX2c6IQ0AW32mTjqmZOh5Y6Gf5OYqTNqVktAeBjmFinhyFaCwW6GYK9YQ==, + } + engines: { node: ^18.19.0 || >=20.6.0 } peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/resources@2.8.0': - resolution: {integrity: sha512-qmXQ27ilDbUK/vGMqwL8D4/rhn76C+sherM4wTbjlfknR8Nvfc/hCxjRJPhkzZzUsPiNg16SA31NxMabwttRjg==} - engines: {node: ^18.19.0 || >=20.6.0} + "@opentelemetry/api": ^1.3.0 + + "@opentelemetry/resources@2.8.0": + resolution: + { + integrity: sha512-qmXQ27ilDbUK/vGMqwL8D4/rhn76C+sherM4wTbjlfknR8Nvfc/hCxjRJPhkzZzUsPiNg16SA31NxMabwttRjg==, + } + engines: { node: ^18.19.0 || >=20.6.0 } peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.10.0' - - '@opentelemetry/sdk-logs@0.219.0': - resolution: {integrity: sha512-s6lTKRakaPClvKoWHRChxnXjDMkM/TQ30ff78jN6EBGf7MI7VzANE5PU3f4z9qDUudWjvZjOLHG0rBnBKYvoXA==} - engines: {node: ^18.19.0 || >=20.6.0} + "@opentelemetry/api": ">=1.3.0 <1.10.0" + + "@opentelemetry/sdk-logs@0.219.0": + resolution: + { + integrity: sha512-s6lTKRakaPClvKoWHRChxnXjDMkM/TQ30ff78jN6EBGf7MI7VzANE5PU3f4z9qDUudWjvZjOLHG0rBnBKYvoXA==, + } + engines: { node: ^18.19.0 || >=20.6.0 } peerDependencies: - '@opentelemetry/api': '>=1.4.0 <1.10.0' - - '@opentelemetry/sdk-metrics@2.8.0': - resolution: {integrity: sha512-UDBGaj6W0Rgy5rTTaoxs8gVGF/aGkAKyjurJv7se6wjRxJu7FoquTLT/vt54DZfo4crbprYfhX/SOK9+BPw1qg==} - engines: {node: ^18.19.0 || >=20.6.0} + "@opentelemetry/api": ">=1.4.0 <1.10.0" + + "@opentelemetry/sdk-metrics@2.8.0": + resolution: + { + integrity: sha512-UDBGaj6W0Rgy5rTTaoxs8gVGF/aGkAKyjurJv7se6wjRxJu7FoquTLT/vt54DZfo4crbprYfhX/SOK9+BPw1qg==, + } + engines: { node: ^18.19.0 || >=20.6.0 } peerDependencies: - '@opentelemetry/api': '>=1.9.0 <1.10.0' - - '@opentelemetry/sdk-trace-base@2.8.0': - resolution: {integrity: sha512-mhU4jp+vW0mGbFRd+GeXHvmfA4aDqWjBjLC3pE5XMpLs0IE2ryYb019Ts2AQrOq67gaTF25D91+fgvEHDZEnuQ==} - engines: {node: ^18.19.0 || >=20.6.0} + "@opentelemetry/api": ">=1.9.0 <1.10.0" + + "@opentelemetry/sdk-trace-base@2.8.0": + resolution: + { + integrity: sha512-mhU4jp+vW0mGbFRd+GeXHvmfA4aDqWjBjLC3pE5XMpLs0IE2ryYb019Ts2AQrOq67gaTF25D91+fgvEHDZEnuQ==, + } + engines: { node: ^18.19.0 || >=20.6.0 } peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.10.0' + "@opentelemetry/api": ">=1.3.0 <1.10.0" + + "@opentelemetry/semantic-conventions@1.41.1": + resolution: + { + integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==, + } + engines: { node: ">=14" } + + "@orama/orama@3.1.18": + resolution: + { + integrity: sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA==, + } + engines: { node: ">= 20.0.0" } + + "@parcel/watcher-android-arm64@2.5.1": + resolution: + { + integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [android] - '@opentelemetry/semantic-conventions@1.41.1': - resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==} - engines: {node: '>=14'} + "@parcel/watcher-darwin-arm64@2.5.1": + resolution: + { + integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [darwin] - '@orama/orama@3.1.18': - resolution: {integrity: sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA==} - engines: {node: '>= 20.0.0'} + "@parcel/watcher-darwin-x64@2.5.1": + resolution: + { + integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [darwin] - '@paulmillr/qr@0.2.1': - resolution: {integrity: sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ==} - deprecated: 'Switch to "qr" (new package name) for security updates: npm install qr' + "@parcel/watcher-freebsd-x64@2.5.1": + resolution: + { + integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [freebsd] - '@posthog/core@1.30.6': - resolution: {integrity: sha512-9X9IUm4Iw9M+nxWOou8LdsvUCyAhDNwzYchMZOcOUVu+CY2oq19GJHC7fZ7UERoUppKVbgWQD51NlfFMHkjGKg==} + "@parcel/watcher-linux-arm-glibc@2.5.1": + resolution: + { + integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm] + os: [linux] + libc: [glibc] - '@posthog/types@1.379.3': - resolution: {integrity: sha512-xx5GLkb/S/eSSQ0H0hnkn1BT7ZG1ZVetQ8/G/h8B5XyOM5prR96a/bgkcIbnK25GFSYyIMNx0X3syvBCYorkUA==} + "@parcel/watcher-linux-arm-musl@2.5.1": + resolution: + { + integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm] + os: [linux] + libc: [musl] - '@protobuf-ts/grpcweb-transport@2.11.1': - resolution: {integrity: sha512-1W4utDdvOB+RHMFQ0soL4JdnxjXV+ddeGIUg08DvZrA8Ms6k5NN6GBFU2oHZdTOcJVpPrDJ02RJlqtaoCMNBtw==} + "@parcel/watcher-linux-arm64-glibc@2.5.1": + resolution: + { + integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [linux] + libc: [glibc] + + "@parcel/watcher-linux-arm64-musl@2.5.1": + resolution: + { + integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [linux] + libc: [musl] + + "@parcel/watcher-linux-x64-glibc@2.5.1": + resolution: + { + integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [linux] + libc: [glibc] + + "@parcel/watcher-linux-x64-musl@2.5.1": + resolution: + { + integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [linux] + libc: [musl] - '@protobuf-ts/runtime-rpc@2.11.1': - resolution: {integrity: sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ==} + "@parcel/watcher-win32-arm64@2.5.1": + resolution: + { + integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [win32] - '@protobuf-ts/runtime@2.11.1': - resolution: {integrity: sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==} + "@parcel/watcher-win32-ia32@2.5.1": + resolution: + { + integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==, + } + engines: { node: ">= 10.0.0" } + cpu: [ia32] + os: [win32] - '@radix-ui/number@1.1.2': - resolution: {integrity: sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==} + "@parcel/watcher-win32-x64@2.5.1": + resolution: + { + integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [win32] - '@radix-ui/primitive@1.1.4': - resolution: {integrity: sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ==} + "@parcel/watcher@2.5.1": + resolution: + { + integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==, + } + engines: { node: ">= 10.0.0" } + + "@paulmillr/qr@0.2.1": + resolution: + { + integrity: sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ==, + } + deprecated: 'Switch to "qr" (new package name) for security updates: npm install qr' - '@radix-ui/react-accordion@1.2.15': - resolution: {integrity: sha512-24Zz/0SYx8F2bSVThBnQrdJs2VbKelyuJordcFRRdA0fRAhrq/wSegGCqaQz34VQoiWqSMGYCYXEhynLSlyQlg==} + "@posthog/core@1.30.6": + resolution: + { + integrity: sha512-9X9IUm4Iw9M+nxWOou8LdsvUCyAhDNwzYchMZOcOUVu+CY2oq19GJHC7fZ7UERoUppKVbgWQD51NlfFMHkjGKg==, + } + + "@posthog/types@1.379.3": + resolution: + { + integrity: sha512-xx5GLkb/S/eSSQ0H0hnkn1BT7ZG1ZVetQ8/G/h8B5XyOM5prR96a/bgkcIbnK25GFSYyIMNx0X3syvBCYorkUA==, + } + + "@protobuf-ts/grpcweb-transport@2.11.1": + resolution: + { + integrity: sha512-1W4utDdvOB+RHMFQ0soL4JdnxjXV+ddeGIUg08DvZrA8Ms6k5NN6GBFU2oHZdTOcJVpPrDJ02RJlqtaoCMNBtw==, + } + + "@protobuf-ts/runtime-rpc@2.11.1": + resolution: + { + integrity: sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ==, + } + + "@protobuf-ts/runtime@2.11.1": + resolution: + { + integrity: sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==, + } + + "@radix-ui/number@1.1.2": + resolution: + { + integrity: sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==, + } + + "@radix-ui/primitive@1.1.4": + resolution: + { + integrity: sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ==, + } + + "@radix-ui/react-accordion@1.2.15": + resolution: + { + integrity: sha512-24Zz/0SYx8F2bSVThBnQrdJs2VbKelyuJordcFRRdA0fRAhrq/wSegGCqaQz34VQoiWqSMGYCYXEhynLSlyQlg==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-arrow@1.1.11': - resolution: {integrity: sha512-Kdil9BB1rIFC/khmf4hC35bn8701AJcizTU7G7cUbEbk5XqqbjDuHW60uUfKqO5WojjZcbAW51Q7P0hRmMLw8A==} + "@radix-ui/react-arrow@1.1.11": + resolution: + { + integrity: sha512-Kdil9BB1rIFC/khmf4hC35bn8701AJcizTU7G7cUbEbk5XqqbjDuHW60uUfKqO5WojjZcbAW51Q7P0hRmMLw8A==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-checkbox@1.3.6': - resolution: {integrity: sha512-eUEUoGMDpfkgHWSE97ZZaUJtzR1M7EKnNIpD1Q16+8JR9NWghcaqMulx9PuCQ720w0UclfYn6FEbCdd5Hx087g==} + "@radix-ui/react-checkbox@1.3.6": + resolution: + { + integrity: sha512-eUEUoGMDpfkgHWSE97ZZaUJtzR1M7EKnNIpD1Q16+8JR9NWghcaqMulx9PuCQ720w0UclfYn6FEbCdd5Hx087g==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-collapsible@1.1.15': - resolution: {integrity: sha512-8A1zibu5skAQ+UVbaeNH5hVMibiFCRJzgMuM14LTWGttnTZKQL9jwYnhAbHRuxrtCqPXa4JvvnVUq1pTNgyZYw==} + "@radix-ui/react-collapsible@1.1.15": + resolution: + { + integrity: sha512-8A1zibu5skAQ+UVbaeNH5hVMibiFCRJzgMuM14LTWGttnTZKQL9jwYnhAbHRuxrtCqPXa4JvvnVUq1pTNgyZYw==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-collection@1.1.11': - resolution: {integrity: sha512-djW9+zeg137KQdlPtmE8xnaD+K2rcXXMWFrSg0hsmYZ6HRbdTA7tDHFgpaW9+huWVEu0RCabL+985T4TA0BE7g==} + "@radix-ui/react-collection@1.1.11": + resolution: + { + integrity: sha512-djW9+zeg137KQdlPtmE8xnaD+K2rcXXMWFrSg0hsmYZ6HRbdTA7tDHFgpaW9+huWVEu0RCabL+985T4TA0BE7g==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-compose-refs@1.1.3': - resolution: {integrity: sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==} + "@radix-ui/react-compose-refs@1.1.3": + resolution: + { + integrity: sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-context@1.1.4': - resolution: {integrity: sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg==} + "@radix-ui/react-context@1.1.4": + resolution: + { + integrity: sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-dialog@1.1.18': - resolution: {integrity: sha512-apa28mldjMgORmE6g/w3sCcA0Y9UAVeeDVoozN4i7kOw12mLl9RBchfzK3Nn6qxOWjrZhK1Lfy7f07kyzxtnBw==} + "@radix-ui/react-dialog@1.1.18": + resolution: + { + integrity: sha512-apa28mldjMgORmE6g/w3sCcA0Y9UAVeeDVoozN4i7kOw12mLl9RBchfzK3Nn6qxOWjrZhK1Lfy7f07kyzxtnBw==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-direction@1.1.2': - resolution: {integrity: sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA==} + "@radix-ui/react-direction@1.1.2": + resolution: + { + integrity: sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-dismissable-layer@1.1.14': - resolution: {integrity: sha512-4lUhWTWAjbDIqFrAPWJ3WqBOpO5YchVZ88X3nh6H9Lu5AFi5nCUeTPj3D8FSDmabmFeRe9ME0BDA4MwKTha5GQ==} + "@radix-ui/react-dismissable-layer@1.1.14": + resolution: + { + integrity: sha512-4lUhWTWAjbDIqFrAPWJ3WqBOpO5YchVZ88X3nh6H9Lu5AFi5nCUeTPj3D8FSDmabmFeRe9ME0BDA4MwKTha5GQ==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-dropdown-menu@2.1.19': - resolution: {integrity: sha512-HZccBkbK0LOi8nYKIp5jll/zIRW0cCOmG6WWyqsSpmXCU+ZlcBbTqIwlBvPCu886C5RVu6c/kHV7xSP8IgYNHw==} + "@radix-ui/react-dropdown-menu@2.1.19": + resolution: + { + integrity: sha512-HZccBkbK0LOi8nYKIp5jll/zIRW0cCOmG6WWyqsSpmXCU+ZlcBbTqIwlBvPCu886C5RVu6c/kHV7xSP8IgYNHw==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-focus-guards@1.1.4': - resolution: {integrity: sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==} + "@radix-ui/react-focus-guards@1.1.4": + resolution: + { + integrity: sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-focus-scope@1.1.11': - resolution: {integrity: sha512-Mn88Vg2whaRocGJNOH+DKFqYm6ySFPQaiwHNxZPyjn99B52KAEJWWY9NP83+nWdk2HM3rdov+STu9AG471Rt9w==} + "@radix-ui/react-focus-scope@1.1.11": + resolution: + { + integrity: sha512-Mn88Vg2whaRocGJNOH+DKFqYm6ySFPQaiwHNxZPyjn99B52KAEJWWY9NP83+nWdk2HM3rdov+STu9AG471Rt9w==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-id@1.1.2': - resolution: {integrity: sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==} + "@radix-ui/react-id@1.1.2": + resolution: + { + integrity: sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-label@2.1.11': - resolution: {integrity: sha512-3PKvDDxOn62k0oV1n4QtNtD2vpu+zYjXR7ojLBPaO6SPvhy53yg0vAmgNeBQeJW5rV3dffoRG+HYfLBZuzw0CQ==} + "@radix-ui/react-label@2.1.11": + resolution: + { + integrity: sha512-3PKvDDxOn62k0oV1n4QtNtD2vpu+zYjXR7ojLBPaO6SPvhy53yg0vAmgNeBQeJW5rV3dffoRG+HYfLBZuzw0CQ==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-menu@2.1.19': - resolution: {integrity: sha512-Mht9BVd1AIsNFVQr4KG3bIK7XQn5IXF0TL/2ObsrzOdc1loaly/+kBDL5roSCYn8j8XZkvpOD0WYLz2FQtH1Eg==} + "@radix-ui/react-menu@2.1.19": + resolution: + { + integrity: sha512-Mht9BVd1AIsNFVQr4KG3bIK7XQn5IXF0TL/2ObsrzOdc1loaly/+kBDL5roSCYn8j8XZkvpOD0WYLz2FQtH1Eg==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-popover@1.1.18': - resolution: {integrity: sha512-qdXDes+eHlnMUGlBAAAe5EG7oOQvqsXuq4mq585diMudg80iB+jHbsSeG3+Q4eWNsogNyhqU2p/3i+Y0iEepqg==} + "@radix-ui/react-popover@1.1.18": + resolution: + { + integrity: sha512-qdXDes+eHlnMUGlBAAAe5EG7oOQvqsXuq4mq585diMudg80iB+jHbsSeG3+Q4eWNsogNyhqU2p/3i+Y0iEepqg==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-popper@1.3.2': - resolution: {integrity: sha512-3QXNeMkdshed1MR3LNoiCirBywRFPkD8ETJa/HlPuLwSajaQixf2ro+isoDNJlGABg9ug41XuZpINZJIle4XWg==} + "@radix-ui/react-popper@1.3.2": + resolution: + { + integrity: sha512-3QXNeMkdshed1MR3LNoiCirBywRFPkD8ETJa/HlPuLwSajaQixf2ro+isoDNJlGABg9ug41XuZpINZJIle4XWg==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-portal@1.1.13': - resolution: {integrity: sha512-z3oXfmaHLJTF1wktbjgD6cn9jiEbq3WSondB10LIuIt2m2Ym4iJlrW04/euMwENDdWDdE7z+OuY7Qyp1YpRSwA==} + "@radix-ui/react-portal@1.1.13": + resolution: + { + integrity: sha512-z3oXfmaHLJTF1wktbjgD6cn9jiEbq3WSondB10LIuIt2m2Ym4iJlrW04/euMwENDdWDdE7z+OuY7Qyp1YpRSwA==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-presence@1.1.6': - resolution: {integrity: sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ==} + "@radix-ui/react-presence@1.1.6": + resolution: + { + integrity: sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-primitive@2.1.7': - resolution: {integrity: sha512-bC3NiwsprbxKjuon9l7X6BUTw7FPVzEYaL92MPEY5SCd/9hUTPXVFtVwRix7778wtRsVao+zE062gL79FZleeQ==} + "@radix-ui/react-primitive@2.1.7": + resolution: + { + integrity: sha512-bC3NiwsprbxKjuon9l7X6BUTw7FPVzEYaL92MPEY5SCd/9hUTPXVFtVwRix7778wtRsVao+zE062gL79FZleeQ==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-roving-focus@1.1.14': - resolution: {integrity: sha512-8Qcnx9447tx/aCBgw6Jenfqg4Skq+vqab9mCBmuGNipIS5YXvL275wbKEu7+ICYHIlAPgCduUMJH1XOYewKF6Q==} + "@radix-ui/react-roving-focus@1.1.14": + resolution: + { + integrity: sha512-8Qcnx9447tx/aCBgw6Jenfqg4Skq+vqab9mCBmuGNipIS5YXvL275wbKEu7+ICYHIlAPgCduUMJH1XOYewKF6Q==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-select@2.3.2': - resolution: {integrity: sha512-brXD6C/V0fVK0DDbscLVw6LsXrjQ+ay8jdOBaN+tLb4vsHsAMm6Gt6eT77wHX1Eq8GPtD5rJ+RxFtfDozsb4+Q==} + "@radix-ui/react-select@2.3.2": + resolution: + { + integrity: sha512-brXD6C/V0fVK0DDbscLVw6LsXrjQ+ay8jdOBaN+tLb4vsHsAMm6Gt6eT77wHX1Eq8GPtD5rJ+RxFtfDozsb4+Q==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-separator@1.1.11': - resolution: {integrity: sha512-jRhe86+8PF7VZ1u14eOWVOuh2BuAhALg/FT1VcMC4OHedMTRUazDnDlKTt+yxo5cRNKHMfmvZ4sSQtWDeMV4CQ==} + "@radix-ui/react-separator@1.1.11": + resolution: + { + integrity: sha512-jRhe86+8PF7VZ1u14eOWVOuh2BuAhALg/FT1VcMC4OHedMTRUazDnDlKTt+yxo5cRNKHMfmvZ4sSQtWDeMV4CQ==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-slot@1.3.0': - resolution: {integrity: sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA==} + "@radix-ui/react-slot@1.3.0": + resolution: + { + integrity: sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-switch@1.3.2': - resolution: {integrity: sha512-tgRBI3DdNwAJYE4BBZyZcz/HRRCvAsPkRvG1wvKc+41tBGMxPn/a87T/wikXAvyDypNQ9kaZwHbeZe+veHCGpA==} + "@radix-ui/react-switch@1.3.2": + resolution: + { + integrity: sha512-tgRBI3DdNwAJYE4BBZyZcz/HRRCvAsPkRvG1wvKc+41tBGMxPn/a87T/wikXAvyDypNQ9kaZwHbeZe+veHCGpA==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-tabs@1.1.16': - resolution: {integrity: sha512-v3Ab2l7z6U7tRB4xA0IyKdq0OsqaO1o9ZjsIEoKKnSZ/l96mZz8aCTX0NCXw+YVHJXr8Km4d+Mn6/Q8YjXa+gw==} + "@radix-ui/react-tabs@1.1.16": + resolution: + { + integrity: sha512-v3Ab2l7z6U7tRB4xA0IyKdq0OsqaO1o9ZjsIEoKKnSZ/l96mZz8aCTX0NCXw+YVHJXr8Km4d+Mn6/Q8YjXa+gw==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-toggle-group@1.1.14': - resolution: {integrity: sha512-TK1vusNKb8IRhF23FTbRgUNZ9zfs5rGIyI7LfR3h26p9LrQ060i0uW9QWeD8baZMddaaP0DBGlIa6pbZG+mitg==} + "@radix-ui/react-toggle-group@1.1.14": + resolution: + { + integrity: sha512-TK1vusNKb8IRhF23FTbRgUNZ9zfs5rGIyI7LfR3h26p9LrQ060i0uW9QWeD8baZMddaaP0DBGlIa6pbZG+mitg==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-toggle@1.1.13': - resolution: {integrity: sha512-bI2ILJrzwgmAsH05TsJ9pVrzqQwAip7OM2/krqAdYn0R16bl86UPWbe5VPHsALat0EnqpV01cGtkleaUKPNdNg==} + "@radix-ui/react-toggle@1.1.13": + resolution: + { + integrity: sha512-bI2ILJrzwgmAsH05TsJ9pVrzqQwAip7OM2/krqAdYn0R16bl86UPWbe5VPHsALat0EnqpV01cGtkleaUKPNdNg==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-tooltip@1.2.11': - resolution: {integrity: sha512-8XZ6Py3y3W2nEzAUGCN5cfVKaUi+CVApcz1d6lrNVVf2hvYEixMRkq8k9ggPKnQUpRRuOV5avt8uvxViH2jLwA==} + "@radix-ui/react-tooltip@1.2.11": + resolution: + { + integrity: sha512-8XZ6Py3y3W2nEzAUGCN5cfVKaUi+CVApcz1d6lrNVVf2hvYEixMRkq8k9ggPKnQUpRRuOV5avt8uvxViH2jLwA==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/react-use-callback-ref@1.1.2': - resolution: {integrity: sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==} + "@radix-ui/react-use-callback-ref@1.1.2": + resolution: + { + integrity: sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-use-controllable-state@1.2.3': - resolution: {integrity: sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==} + "@radix-ui/react-use-controllable-state@1.2.3": + resolution: + { + integrity: sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-use-effect-event@0.0.3': - resolution: {integrity: sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==} + "@radix-ui/react-use-effect-event@0.0.3": + resolution: + { + integrity: sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-use-layout-effect@1.1.2': - resolution: {integrity: sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==} + "@radix-ui/react-use-layout-effect@1.1.2": + resolution: + { + integrity: sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-use-previous@1.1.2': - resolution: {integrity: sha512-IGBQPtRFdhN6MQ8dbegVmBq1LVZluya3F1jWY+puIcQC3MHctRwTDSBWCkL/3ZcnMJLTMJ++Z+ktmvg0F89iCw==} + "@radix-ui/react-use-previous@1.1.2": + resolution: + { + integrity: sha512-IGBQPtRFdhN6MQ8dbegVmBq1LVZluya3F1jWY+puIcQC3MHctRwTDSBWCkL/3ZcnMJLTMJ++Z+ktmvg0F89iCw==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-use-rect@1.1.2': - resolution: {integrity: sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw==} + "@radix-ui/react-use-rect@1.1.2": + resolution: + { + integrity: sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-use-size@1.1.2': - resolution: {integrity: sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w==} + "@radix-ui/react-use-size@1.1.2": + resolution: + { + integrity: sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w==, + } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@radix-ui/react-visually-hidden@1.2.7': - resolution: {integrity: sha512-1wNZBggTDK3GRuuQ6nP4k2yi7a6l7I5qbMPbZcRsrGsGVead/f/d5FhEzUvqFs0bcrDLx7n1zKQ3JvLR6whaaw==} + "@radix-ui/react-visually-hidden@1.2.7": + resolution: + { + integrity: sha512-1wNZBggTDK3GRuuQ6nP4k2yi7a6l7I5qbMPbZcRsrGsGVead/f/d5FhEzUvqFs0bcrDLx7n1zKQ3JvLR6whaaw==, + } peerDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true - '@types/react-dom': + "@types/react-dom": optional: true - '@radix-ui/rect@1.1.2': - resolution: {integrity: sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==} - - '@reown/appkit-common@1.7.8': - resolution: {integrity: sha512-ridIhc/x6JOp7KbDdwGKY4zwf8/iK8EYBl+HtWrruutSLwZyVi5P8WaZa+8iajL6LcDcDF7LoyLwMTym7SRuwQ==} - - '@reown/appkit-controllers@1.7.8': - resolution: {integrity: sha512-IdXlJlivrlj6m63VsGLsjtPHHsTWvKGVzWIP1fXZHVqmK+rZCBDjCi9j267Rb9/nYRGHWBtlFQhO8dK35WfeDA==} - - '@reown/appkit-pay@1.7.8': - resolution: {integrity: sha512-OSGQ+QJkXx0FEEjlpQqIhT8zGJKOoHzVnyy/0QFrl3WrQTjCzg0L6+i91Ad5Iy1zb6V5JjqtfIFpRVRWN4M3pw==} - - '@reown/appkit-polyfills@1.7.8': - resolution: {integrity: sha512-W/kq786dcHHAuJ3IV2prRLEgD/2iOey4ueMHf1sIFjhhCGMynMkhsOhQMUH0tzodPqUgAC494z4bpIDYjwWXaA==} - - '@reown/appkit-scaffold-ui@1.7.8': - resolution: {integrity: sha512-RCeHhAwOrIgcvHwYlNWMcIDibdI91waaoEYBGw71inE0kDB8uZbE7tE6DAXJmDkvl0qPh+DqlC4QbJLF1FVYdQ==} - - '@reown/appkit-ui@1.7.8': - resolution: {integrity: sha512-1hjCKjf6FLMFzrulhl0Y9Vb9Fu4royE+SXCPSWh4VhZhWqlzUFc7kutnZKx8XZFVQH4pbBvY62SpRC93gqoHow==} - - '@reown/appkit-utils@1.7.8': - resolution: {integrity: sha512-8X7UvmE8GiaoitCwNoB86pttHgQtzy4ryHZM9kQpvjQ0ULpiER44t1qpVLXNM4X35O0v18W0Dk60DnYRMH2WRw==} + "@radix-ui/rect@1.1.2": + resolution: + { + integrity: sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==, + } + + "@reown/appkit-common@1.7.8": + resolution: + { + integrity: sha512-ridIhc/x6JOp7KbDdwGKY4zwf8/iK8EYBl+HtWrruutSLwZyVi5P8WaZa+8iajL6LcDcDF7LoyLwMTym7SRuwQ==, + } + + "@reown/appkit-controllers@1.7.8": + resolution: + { + integrity: sha512-IdXlJlivrlj6m63VsGLsjtPHHsTWvKGVzWIP1fXZHVqmK+rZCBDjCi9j267Rb9/nYRGHWBtlFQhO8dK35WfeDA==, + } + + "@reown/appkit-pay@1.7.8": + resolution: + { + integrity: sha512-OSGQ+QJkXx0FEEjlpQqIhT8zGJKOoHzVnyy/0QFrl3WrQTjCzg0L6+i91Ad5Iy1zb6V5JjqtfIFpRVRWN4M3pw==, + } + + "@reown/appkit-polyfills@1.7.8": + resolution: + { + integrity: sha512-W/kq786dcHHAuJ3IV2prRLEgD/2iOey4ueMHf1sIFjhhCGMynMkhsOhQMUH0tzodPqUgAC494z4bpIDYjwWXaA==, + } + + "@reown/appkit-scaffold-ui@1.7.8": + resolution: + { + integrity: sha512-RCeHhAwOrIgcvHwYlNWMcIDibdI91waaoEYBGw71inE0kDB8uZbE7tE6DAXJmDkvl0qPh+DqlC4QbJLF1FVYdQ==, + } + + "@reown/appkit-ui@1.7.8": + resolution: + { + integrity: sha512-1hjCKjf6FLMFzrulhl0Y9Vb9Fu4royE+SXCPSWh4VhZhWqlzUFc7kutnZKx8XZFVQH4pbBvY62SpRC93gqoHow==, + } + + "@reown/appkit-utils@1.7.8": + resolution: + { + integrity: sha512-8X7UvmE8GiaoitCwNoB86pttHgQtzy4ryHZM9kQpvjQ0ULpiER44t1qpVLXNM4X35O0v18W0Dk60DnYRMH2WRw==, + } peerDependencies: valtio: 1.13.2 - '@reown/appkit-wallet@1.7.8': - resolution: {integrity: sha512-kspz32EwHIOT/eg/ZQbFPxgXq0B/olDOj3YMu7gvLEFz4xyOFd/wgzxxAXkp5LbG4Cp++s/elh79rVNmVFdB9A==} - - '@reown/appkit@1.7.8': - resolution: {integrity: sha512-51kTleozhA618T1UvMghkhKfaPcc9JlKwLJ5uV+riHyvSoWPKPRIa5A6M1Wano5puNyW0s3fwywhyqTHSilkaA==} - - '@rtsao/scc@1.1.0': - resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - - '@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'} + "@reown/appkit-wallet@1.7.8": + resolution: + { + integrity: sha512-kspz32EwHIOT/eg/ZQbFPxgXq0B/olDOj3YMu7gvLEFz4xyOFd/wgzxxAXkp5LbG4Cp++s/elh79rVNmVFdB9A==, + } + + "@reown/appkit@1.7.8": + resolution: + { + integrity: sha512-51kTleozhA618T1UvMghkhKfaPcc9JlKwLJ5uV+riHyvSoWPKPRIa5A6M1Wano5puNyW0s3fwywhyqTHSilkaA==, + } + + "@rtsao/scc@1.1.0": + resolution: + { + integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==, + } + + "@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.1.9': - resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} - - '@scure/base@1.2.6': - resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} - - '@scure/bip32@1.4.0': - resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} - - '@scure/bip32@1.6.2': - resolution: {integrity: sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==} - - '@scure/bip32@1.7.0': - resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==} - - '@scure/bip39@1.3.0': - resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} - - '@scure/bip39@1.5.4': - resolution: {integrity: sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==} - - '@scure/bip39@1.6.0': - resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==} - - '@shikijs/core@1.29.2': - resolution: {integrity: sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ==} - - '@shikijs/core@4.3.0': - resolution: {integrity: sha512-EooU3i9F6IAE8kEu+AnGf9DFZWkQBZ+hJn3tLVbsH+61mtQiva5biai66fAA6nvFPXkLgvrh7BrR7YcJU83xQQ==} - engines: {node: '>=20'} - - '@shikijs/engine-javascript@1.29.2': - resolution: {integrity: sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A==} - - '@shikijs/engine-javascript@4.3.0': - resolution: {integrity: sha512-hTv/KiFf2tpiqlACPiztGGurEARWIutB8YUhcrA1pUC7VzzwKO+g5crUocrLztrZ5ro5Z4hbXg7bYclETn3gSQ==} - engines: {node: '>=20'} - - '@shikijs/engine-oniguruma@1.29.2': - resolution: {integrity: sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==} - - '@shikijs/engine-oniguruma@4.3.0': - resolution: {integrity: sha512-1vMdN3gHfnKfLYwecUI2ITJI4RhHt96xEaJumVn7Heb0IlJ8WQMIH0Voak+2j22BpSNKdnOfB/pCTPnPm2gq7A==} - engines: {node: '>=20'} - - '@shikijs/langs@1.29.2': - resolution: {integrity: sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==} - - '@shikijs/langs@4.3.0': - resolution: {integrity: sha512-rnlqFbBRSys9bT4gl/5rw9RnS0W/I84ZldXPkO7cvlEMoV85TyF/aU01N7/NbSR776RNLjrJKjfFUXJR6wN1Cg==} - engines: {node: '>=20'} - - '@shikijs/primitive@4.3.0': - resolution: {integrity: sha512-CPkz64PTa5diRW1ggzMZH9VM/du4RNChYgVtgqrFcgruvIybmCvySv8GkiHSczUHXYuuR8TdKEwFx+UnZMpgdg==} - engines: {node: '>=20'} - - '@shikijs/themes@1.29.2': - resolution: {integrity: sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g==} - - '@shikijs/themes@4.3.0': - resolution: {integrity: sha512-Avgt05YiT+Y3prjIc9lmQxhJzHBcCfR6cjiFW4OyaMBbt2A6trX5rfjUzx+Vj/mE9qpArYjatnqo9XPjQNW/AQ==} - engines: {node: '>=20'} - - '@shikijs/types@1.29.2': - resolution: {integrity: sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==} - - '@shikijs/types@4.3.0': - resolution: {integrity: sha512-oc8b9U2SYvofKZk8e/737nIX0qwf6eV2vHFATeObAu7r+mUVpLs8Re0BmVkIjAWAYgkmG/CzLNo7rzuBzRu/wQ==} - engines: {node: '>=20'} - - '@shikijs/vscode-textmate@10.0.2': - resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - - '@socket.io/component-emitter@3.1.2': - resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} - - '@solana-program/system@0.10.0': - resolution: {integrity: sha512-Go+LOEZmqmNlfr+Gjy5ZWAdY5HbYzk2RBewD9QinEU/bBSzpFfzqDRT55JjFRBGJUvMgf3C2vfXEGT4i8DSI4g==} + "@scure/base@1.1.9": + resolution: + { + integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==, + } + + "@scure/base@1.2.6": + resolution: + { + integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==, + } + + "@scure/bip32@1.4.0": + resolution: + { + integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==, + } + + "@scure/bip32@1.6.2": + resolution: + { + integrity: sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==, + } + + "@scure/bip32@1.7.0": + resolution: + { + integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==, + } + + "@scure/bip39@1.3.0": + resolution: + { + integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==, + } + + "@scure/bip39@1.5.4": + resolution: + { + integrity: sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==, + } + + "@scure/bip39@1.6.0": + resolution: + { + integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==, + } + + "@shikijs/core@1.29.2": + resolution: + { + integrity: sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ==, + } + + "@shikijs/core@4.3.0": + resolution: + { + integrity: sha512-EooU3i9F6IAE8kEu+AnGf9DFZWkQBZ+hJn3tLVbsH+61mtQiva5biai66fAA6nvFPXkLgvrh7BrR7YcJU83xQQ==, + } + engines: { node: ">=20" } + + "@shikijs/engine-javascript@1.29.2": + resolution: + { + integrity: sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A==, + } + + "@shikijs/engine-javascript@4.3.0": + resolution: + { + integrity: sha512-hTv/KiFf2tpiqlACPiztGGurEARWIutB8YUhcrA1pUC7VzzwKO+g5crUocrLztrZ5ro5Z4hbXg7bYclETn3gSQ==, + } + engines: { node: ">=20" } + + "@shikijs/engine-oniguruma@1.29.2": + resolution: + { + integrity: sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==, + } + + "@shikijs/engine-oniguruma@4.3.0": + resolution: + { + integrity: sha512-1vMdN3gHfnKfLYwecUI2ITJI4RhHt96xEaJumVn7Heb0IlJ8WQMIH0Voak+2j22BpSNKdnOfB/pCTPnPm2gq7A==, + } + engines: { node: ">=20" } + + "@shikijs/langs@1.29.2": + resolution: + { + integrity: sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==, + } + + "@shikijs/langs@4.3.0": + resolution: + { + integrity: sha512-rnlqFbBRSys9bT4gl/5rw9RnS0W/I84ZldXPkO7cvlEMoV85TyF/aU01N7/NbSR776RNLjrJKjfFUXJR6wN1Cg==, + } + engines: { node: ">=20" } + + "@shikijs/primitive@4.3.0": + resolution: + { + integrity: sha512-CPkz64PTa5diRW1ggzMZH9VM/du4RNChYgVtgqrFcgruvIybmCvySv8GkiHSczUHXYuuR8TdKEwFx+UnZMpgdg==, + } + engines: { node: ">=20" } + + "@shikijs/themes@1.29.2": + resolution: + { + integrity: sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g==, + } + + "@shikijs/themes@4.3.0": + resolution: + { + integrity: sha512-Avgt05YiT+Y3prjIc9lmQxhJzHBcCfR6cjiFW4OyaMBbt2A6trX5rfjUzx+Vj/mE9qpArYjatnqo9XPjQNW/AQ==, + } + engines: { node: ">=20" } + + "@shikijs/types@1.29.2": + resolution: + { + integrity: sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==, + } + + "@shikijs/types@4.3.0": + resolution: + { + integrity: sha512-oc8b9U2SYvofKZk8e/737nIX0qwf6eV2vHFATeObAu7r+mUVpLs8Re0BmVkIjAWAYgkmG/CzLNo7rzuBzRu/wQ==, + } + engines: { node: ">=20" } + + "@shikijs/vscode-textmate@10.0.2": + resolution: + { + integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==, + } + + "@socket.io/component-emitter@3.1.2": + resolution: + { + integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==, + } + + "@solana-program/system@0.10.0": + resolution: + { + integrity: sha512-Go+LOEZmqmNlfr+Gjy5ZWAdY5HbYzk2RBewD9QinEU/bBSzpFfzqDRT55JjFRBGJUvMgf3C2vfXEGT4i8DSI4g==, + } peerDependencies: - '@solana/kit': ^5.0 + "@solana/kit": ^5.0 - '@solana-program/token@0.9.0': - resolution: {integrity: sha512-vnZxndd4ED4Fc56sw93cWZ2djEeeOFxtaPS8SPf5+a+JZjKA/EnKqzbE1y04FuMhIVrLERQ8uR8H2h72eZzlsA==} + "@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'} + "@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'} + "@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'} + "@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/buffer-layout@4.0.1': - resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} - engines: {node: '>=5.10'} - - '@solana/codecs-core@2.3.0': - resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==} - engines: {node: '>=20.18.0'} + "@solana/buffer-layout@4.0.1": + resolution: + { + integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==, + } + engines: { node: ">=5.10" } + + "@solana/codecs-core@2.3.0": + resolution: + { + integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==, + } + engines: { node: ">=20.18.0" } peerDependencies: - typescript: '>=5.3.3' - - '@solana/codecs-core@5.5.1': - resolution: {integrity: sha512-TgBt//bbKBct0t6/MpA8ElaOA3sa8eYVvR7LGslCZ84WiAwwjCY0lW/lOYsFHJQzwREMdUyuEyy5YWBKtdh8Rw==} - engines: {node: '>=20.18.0'} + typescript: ">=5.3.3" + + "@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'} + "@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@2.3.0': - resolution: {integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==} - engines: {node: '>=20.18.0'} + "@solana/codecs-numbers@2.3.0": + resolution: + { + integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==, + } + engines: { node: ">=20.18.0" } peerDependencies: - typescript: '>=5.3.3' - - '@solana/codecs-numbers@5.5.1': - resolution: {integrity: sha512-rllMIZAHqmtvC0HO/dc/21wDuWaD0B8Ryv8o+YtsICQBuiL/0U4AGwH7Pi5GNFySYk0/crSuwfIqQFtmxNSPFw==} - engines: {node: '>=20.18.0'} + typescript: ">=5.3.3" + + "@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'} + "@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 @@ -2122,25 +3282,34 @@ packages: typescript: optional: true - '@solana/codecs@5.5.1': - resolution: {integrity: sha512-Vea29nJub/bXjfzEV7ZZQ/PWr1pYLZo3z0qW0LQL37uKKVzVFRQlwetd7INk3YtTD3xm9WUYr7bCvYUk3uKy2g==} - engines: {node: '>=20.18.0'} + "@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@2.3.0': - resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==} - engines: {node: '>=20.18.0'} + "@solana/errors@2.3.0": + resolution: + { + integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==, + } + engines: { node: ">=20.18.0" } hasBin: true peerDependencies: - typescript: '>=5.3.3' - - '@solana/errors@5.5.1': - resolution: {integrity: sha512-vFO3p+S7HoyyrcAectnXbdsMfwUzY2zYFUc2DEe5BwpiE9J1IAxPBGjOWO6hL1bbYdBrlmjNx8DXCslqS+Kcmg==} - engines: {node: '>=20.18.0'} + typescript: ">=5.3.3" + + "@solana/errors@5.5.1": + resolution: + { + integrity: sha512-vFO3p+S7HoyyrcAectnXbdsMfwUzY2zYFUc2DEe5BwpiE9J1IAxPBGjOWO6hL1bbYdBrlmjNx8DXCslqS+Kcmg==, + } + engines: { node: ">=20.18.0" } hasBin: true peerDependencies: typescript: ^5.0.0 @@ -2148,781 +3317,1357 @@ packages: typescript: optional: true - '@solana/fast-stable-stringify@5.5.1': - resolution: {integrity: sha512-Ni7s2FN33zTzhTFgRjEbOVFO+UAmK8qi3Iu0/GRFYK4jN696OjKHnboSQH/EacQ+yGqS54bfxf409wU5dsLLCw==} - engines: {node: '>=20.18.0'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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'} + "@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 - '@solana/web3.js@1.98.4': - resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==} - - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - - '@swc/helpers@0.5.15': - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - - '@swc/helpers@0.5.23': - resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} + "@solana/web3.js@1.98.4": + resolution: + { + integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==, + } + + "@standard-schema/spec@1.1.0": + resolution: + { + integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==, + } + + "@swc/helpers@0.5.15": + resolution: + { + integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==, + } + + "@swc/helpers@0.5.23": + resolution: + { + integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==, + } + + "@tailwindcss/cli@4.3.3": + resolution: + { + integrity: sha512-ZvS/n1ZHOBKcVlhkt8l5NNr1EDXk1NboYO5CYDOs6NUmvT9z6bzkwsosaJftY57T/3gWNzWMJzIXLodZC8ssdw==, + } + hasBin: true - '@tailwindcss/node@4.3.2': - resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} + "@tailwindcss/node@4.3.2": + resolution: + { + integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==, + } + + "@tailwindcss/node@4.3.3": + resolution: + { + integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==, + } + + "@tailwindcss/oxide-android-arm64@4.3.2": + resolution: + { + integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==, + } + engines: { node: ">= 20" } + cpu: [arm64] + os: [android] - '@tailwindcss/oxide-android-arm64@4.3.2': - resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-android-arm64@4.3.3": + resolution: + { + integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==, + } + engines: { node: ">= 20" } cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.3.2': - resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-darwin-arm64@4.3.2": + resolution: + { + integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==, + } + engines: { node: ">= 20" } + cpu: [arm64] + os: [darwin] + + "@tailwindcss/oxide-darwin-arm64@4.3.3": + resolution: + { + integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==, + } + engines: { node: ">= 20" } cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.3.2': - resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-darwin-x64@4.3.2": + resolution: + { + integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==, + } + engines: { node: ">= 20" } + cpu: [x64] + os: [darwin] + + "@tailwindcss/oxide-darwin-x64@4.3.3": + resolution: + { + integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==, + } + engines: { node: ">= 20" } cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.3.2': - resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-freebsd-x64@4.3.2": + resolution: + { + integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==, + } + engines: { node: ">= 20" } cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': - resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-freebsd-x64@4.3.3": + resolution: + { + integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==, + } + engines: { node: ">= 20" } + cpu: [x64] + os: [freebsd] + + "@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2": + resolution: + { + integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==, + } + engines: { node: ">= 20" } + cpu: [arm] + os: [linux] + + "@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3": + resolution: + { + integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==, + } + engines: { node: ">= 20" } cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': - resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-linux-arm64-gnu@4.3.2": + resolution: + { + integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==, + } + engines: { node: ">= 20" } cpu: [arm64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-arm64-musl@4.3.2': - resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-linux-arm64-gnu@4.3.3": + resolution: + { + integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==, + } + engines: { node: ">= 20" } + cpu: [arm64] + os: [linux] + libc: [glibc] + + "@tailwindcss/oxide-linux-arm64-musl@4.3.2": + resolution: + { + integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==, + } + engines: { node: ">= 20" } cpu: [arm64] os: [linux] libc: [musl] - '@tailwindcss/oxide-linux-x64-gnu@4.3.2': - resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-linux-arm64-musl@4.3.3": + resolution: + { + integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==, + } + engines: { node: ">= 20" } + cpu: [arm64] + os: [linux] + libc: [musl] + + "@tailwindcss/oxide-linux-x64-gnu@4.3.2": + resolution: + { + integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==, + } + engines: { node: ">= 20" } + cpu: [x64] + os: [linux] + libc: [glibc] + + "@tailwindcss/oxide-linux-x64-gnu@4.3.3": + resolution: + { + integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==, + } + engines: { node: ">= 20" } cpu: [x64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-x64-musl@4.3.2': - resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-linux-x64-musl@4.3.2": + resolution: + { + integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==, + } + engines: { node: ">= 20" } + cpu: [x64] + os: [linux] + libc: [musl] + + "@tailwindcss/oxide-linux-x64-musl@4.3.3": + resolution: + { + integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==, + } + engines: { node: ">= 20" } cpu: [x64] os: [linux] libc: [musl] - '@tailwindcss/oxide-wasm32-wasi@4.3.2': - resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==} - engines: {node: '>=14.0.0'} + "@tailwindcss/oxide-wasm32-wasi@4.3.2": + resolution: + { + integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==, + } + engines: { node: ">=14.0.0" } + cpu: [wasm32] + bundledDependencies: + - "@napi-rs/wasm-runtime" + - "@emnapi/core" + - "@emnapi/runtime" + - "@tybys/wasm-util" + - "@emnapi/wasi-threads" + - tslib + + "@tailwindcss/oxide-wasm32-wasi@4.3.3": + resolution: + { + integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==, + } + engines: { node: ">=14.0.0" } cpu: [wasm32] bundledDependencies: - - '@napi-rs/wasm-runtime' - - '@emnapi/core' - - '@emnapi/runtime' - - '@tybys/wasm-util' - - '@emnapi/wasi-threads' + - "@napi-rs/wasm-runtime" + - "@emnapi/core" + - "@emnapi/runtime" + - "@tybys/wasm-util" + - "@emnapi/wasi-threads" - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': - resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==} - engines: {node: '>= 20'} + "@tailwindcss/oxide-win32-arm64-msvc@4.3.2": + resolution: + { + integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==, + } + engines: { node: ">= 20" } cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.3.2': - resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==} - engines: {node: '>= 20'} - cpu: [x64] + "@tailwindcss/oxide-win32-arm64-msvc@4.3.3": + resolution: + { + integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==, + } + engines: { node: ">= 20" } + cpu: [arm64] os: [win32] - '@tailwindcss/oxide@4.3.2': - resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==} - engines: {node: '>= 20'} - - '@tailwindcss/postcss@4.3.2': - resolution: {integrity: sha512-rjVWYCa7Ngbi5AarT6k8TkxUG3Wl1QKzHdIZVsjZSzf36Jmo2IKZt/NHRAwly8oDkbBOH0YTu+CHuf9jPxMc+g==} + "@tailwindcss/oxide-win32-x64-msvc@4.3.2": + resolution: + { + integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==, + } + engines: { node: ">= 20" } + cpu: [x64] + os: [win32] - '@tanstack/query-core@5.101.2': - resolution: {integrity: sha512-hH5MLoJhF7KaIGd7q3xTXGXvslI+GYlM1Z/35aSHHWaCJWB7XvTSHYuV3eM7tw+aE0mT/xMro4M4Q9rCGHT0lw==} + "@tailwindcss/oxide-win32-x64-msvc@4.3.3": + resolution: + { + integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==, + } + engines: { node: ">= 20" } + cpu: [x64] + os: [win32] - '@tanstack/react-query@5.101.2': - resolution: {integrity: sha512-seDkr6kzGzX1okaaTtZPtgA688CDPlXUz1C6xSg0ESqn04Vuc8tlrYms1s3de+znBqhPVxFRfpAfUf+6XvfPWg==} + "@tailwindcss/oxide@4.3.2": + resolution: + { + integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==, + } + engines: { node: ">= 20" } + + "@tailwindcss/oxide@4.3.3": + resolution: + { + integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==, + } + engines: { node: ">= 20" } + + "@tailwindcss/postcss@4.3.2": + resolution: + { + integrity: sha512-rjVWYCa7Ngbi5AarT6k8TkxUG3Wl1QKzHdIZVsjZSzf36Jmo2IKZt/NHRAwly8oDkbBOH0YTu+CHuf9jPxMc+g==, + } + + "@tanstack/query-core@5.101.2": + resolution: + { + integrity: sha512-hH5MLoJhF7KaIGd7q3xTXGXvslI+GYlM1Z/35aSHHWaCJWB7XvTSHYuV3eM7tw+aE0mT/xMro4M4Q9rCGHT0lw==, + } + + "@tanstack/react-query@5.101.2": + resolution: + { + integrity: sha512-seDkr6kzGzX1okaaTtZPtgA688CDPlXUz1C6xSg0ESqn04Vuc8tlrYms1s3de+znBqhPVxFRfpAfUf+6XvfPWg==, + } peerDependencies: react: ^18 || ^19 - '@ts-morph/common@0.19.0': - resolution: {integrity: sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ==} - - '@tsconfig/node10@1.0.12': - resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} - - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - - '@tybys/wasm-util@0.10.3': - resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} - - '@types/connect@3.4.38': - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - - '@types/debug@4.1.13': - resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} - - '@types/estree-jsx@1.0.5': - resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} - - '@types/estree@1.0.9': - resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - - '@types/hast@3.0.4': - resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - - '@types/lodash@4.17.24': - resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} - - '@types/mdast@4.0.4': - resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - - '@types/mdx@2.0.14': - resolution: {integrity: sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==} - - '@types/ms@2.1.0': - resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - - '@types/node@12.20.55': - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - - '@types/node@20.19.43': - resolution: {integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==} - - '@types/node@22.7.5': - resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} - - '@types/react-dom@19.1.2': - resolution: {integrity: sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==} + "@ts-morph/common@0.19.0": + resolution: + { + integrity: sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ==, + } + + "@tsconfig/node10@1.0.12": + resolution: + { + integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==, + } + + "@tsconfig/node12@1.0.11": + resolution: + { + integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==, + } + + "@tsconfig/node14@1.0.3": + resolution: + { + integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==, + } + + "@tsconfig/node16@1.0.4": + resolution: + { + integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==, + } + + "@tybys/wasm-util@0.10.3": + resolution: + { + integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==, + } + + "@types/connect@3.4.38": + resolution: + { + integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==, + } + + "@types/debug@4.1.13": + resolution: + { + integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==, + } + + "@types/estree-jsx@1.0.5": + resolution: + { + integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==, + } + + "@types/estree@1.0.9": + resolution: + { + integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==, + } + + "@types/hast@3.0.4": + resolution: + { + integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==, + } + + "@types/json-schema@7.0.15": + resolution: + { + integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, + } + + "@types/json5@0.0.29": + resolution: + { + integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==, + } + + "@types/lodash@4.17.24": + resolution: + { + integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==, + } + + "@types/mdast@4.0.4": + resolution: + { + integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==, + } + + "@types/mdx@2.0.14": + resolution: + { + integrity: sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==, + } + + "@types/ms@2.1.0": + resolution: + { + integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==, + } + + "@types/node@12.20.55": + resolution: + { + integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==, + } + + "@types/node@20.19.43": + resolution: + { + integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==, + } + + "@types/node@22.7.5": + resolution: + { + integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==, + } + + "@types/react-dom@19.1.2": + resolution: + { + integrity: sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==, + } peerDependencies: - '@types/react': 19.1.2 - - '@types/react@19.1.2': - resolution: {integrity: sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==} - - '@types/set-cookie-parser@2.4.10': - resolution: {integrity: sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw==} - - '@types/statuses@2.0.6': - resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} - - '@types/trusted-types@2.0.7': - resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - - '@types/unist@2.0.11': - resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - - '@types/unist@3.0.3': - resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - - '@types/uuid@10.0.0': - resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} - - '@types/ws@7.4.7': - resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} - - '@types/ws@8.18.1': - resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - - '@typescript-eslint/eslint-plugin@8.62.1': - resolution: {integrity: sha512-4EQM77WgVNxj7OkL/5b/D/xZsw00G577+UriYTC7JF5opcF3T2AuoeY7ueLaZgSVjSgCS6yOAJB5bRGLPSJUzA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + "@types/react": 19.1.2 + + "@types/react-test-renderer@19.1.0": + resolution: + { + integrity: sha512-XD0WZrHqjNrxA/MaR9O22w/RNidWR9YZmBdRGI7wcnWGrv/3dA8wKCJ8m63Sn+tLJhcjmuhOi629N66W6kgWzQ==, + } + + "@types/react@19.1.2": + resolution: + { + integrity: sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==, + } + + "@types/set-cookie-parser@2.4.10": + resolution: + { + integrity: sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw==, + } + + "@types/statuses@2.0.6": + resolution: + { + integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==, + } + + "@types/trusted-types@2.0.7": + resolution: + { + integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==, + } + + "@types/unist@2.0.11": + resolution: + { + integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==, + } + + "@types/unist@3.0.3": + resolution: + { + integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==, + } + + "@types/uuid@10.0.0": + resolution: + { + integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==, + } + + "@types/ws@7.4.7": + resolution: + { + integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==, + } + + "@types/ws@8.18.1": + resolution: + { + integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==, + } + + "@typescript-eslint/eslint-plugin@8.62.1": + resolution: + { + integrity: sha512-4EQM77WgVNxj7OkL/5b/D/xZsw00G577+UriYTC7JF5opcF3T2AuoeY7ueLaZgSVjSgCS6yOAJB5bRGLPSJUzA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: - '@typescript-eslint/parser': ^8.62.1 + "@typescript-eslint/parser": ^8.62.1 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/parser@8.62.1': - resolution: {integrity: sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/parser@8.62.1": + resolution: + { + integrity: sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/project-service@8.62.1': - resolution: {integrity: sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/project-service@8.62.1": + resolution: + { + integrity: sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/scope-manager@8.62.1': - resolution: {integrity: sha512-r4d249KbQ1SFdpeStvob8Ih6aPPIzfqllPVOtvhve6ZcpuVcYo5/7zUWckKpHE7StASX4kTKZTLf0WQm/wPkcg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/tsconfig-utils@8.62.1': - resolution: {integrity: sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/scope-manager@8.62.1": + resolution: + { + integrity: sha512-r4d249KbQ1SFdpeStvob8Ih6aPPIzfqllPVOtvhve6ZcpuVcYo5/7zUWckKpHE7StASX4kTKZTLf0WQm/wPkcg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@typescript-eslint/tsconfig-utils@8.62.1": + resolution: + { + integrity: sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/type-utils@8.62.1': - resolution: {integrity: sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/type-utils@8.62.1": + resolution: + { + integrity: sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/types@8.62.1': - resolution: {integrity: sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.62.1': - resolution: {integrity: sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/types@8.62.1": + resolution: + { + integrity: sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@typescript-eslint/typescript-estree@8.62.1": + resolution: + { + integrity: sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/utils@8.62.1': - resolution: {integrity: sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/utils@8.62.1": + resolution: + { + integrity: sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - '@typescript-eslint/visitor-keys@8.62.1': - resolution: {integrity: sha512-4g3BLxfdTMy8iZG0MaBkadnlRrCJ74cQiFbyEVMrkwIoqdyaXXQM22cotDvrl4x28wgIZ9rEJRoM+mmhSJpJ1g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@ungap/structured-clone@1.3.2': - resolution: {integrity: sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA==} - - '@unrs/resolver-binding-android-arm-eabi@1.12.2': - resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==} + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/visitor-keys@8.62.1": + resolution: + { + integrity: sha512-4g3BLxfdTMy8iZG0MaBkadnlRrCJ74cQiFbyEVMrkwIoqdyaXXQM22cotDvrl4x28wgIZ9rEJRoM+mmhSJpJ1g==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@ungap/structured-clone@1.3.2": + resolution: + { + integrity: sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA==, + } + + "@unrs/resolver-binding-android-arm-eabi@1.12.2": + resolution: + { + integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==, + } cpu: [arm] os: [android] - '@unrs/resolver-binding-android-arm64@1.12.2': - resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==} + "@unrs/resolver-binding-android-arm64@1.12.2": + resolution: + { + integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==, + } cpu: [arm64] os: [android] - '@unrs/resolver-binding-darwin-arm64@1.12.2': - resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==} + "@unrs/resolver-binding-darwin-arm64@1.12.2": + resolution: + { + integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==, + } cpu: [arm64] os: [darwin] - '@unrs/resolver-binding-darwin-x64@1.12.2': - resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==} + "@unrs/resolver-binding-darwin-x64@1.12.2": + resolution: + { + integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==, + } cpu: [x64] os: [darwin] - '@unrs/resolver-binding-freebsd-x64@1.12.2': - resolution: {integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==} + "@unrs/resolver-binding-freebsd-x64@1.12.2": + resolution: + { + integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==, + } cpu: [x64] os: [freebsd] - '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': - resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==} + "@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2": + resolution: + { + integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==, + } cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': - resolution: {integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==} + "@unrs/resolver-binding-linux-arm-musleabihf@1.12.2": + resolution: + { + integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==, + } cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': - resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==} + "@unrs/resolver-binding-linux-arm64-gnu@1.12.2": + resolution: + { + integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==, + } cpu: [arm64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-arm64-musl@1.12.2': - resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==} + "@unrs/resolver-binding-linux-arm64-musl@1.12.2": + resolution: + { + integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==, + } cpu: [arm64] os: [linux] libc: [musl] - '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': - resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==} + "@unrs/resolver-binding-linux-loong64-gnu@1.12.2": + resolution: + { + integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==, + } cpu: [loong64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-loong64-musl@1.12.2': - resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==} + "@unrs/resolver-binding-linux-loong64-musl@1.12.2": + resolution: + { + integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==, + } cpu: [loong64] os: [linux] libc: [musl] - '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': - resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==} + "@unrs/resolver-binding-linux-ppc64-gnu@1.12.2": + resolution: + { + integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==, + } cpu: [ppc64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': - resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==} + "@unrs/resolver-binding-linux-riscv64-gnu@1.12.2": + resolution: + { + integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==, + } cpu: [riscv64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': - resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==} + "@unrs/resolver-binding-linux-riscv64-musl@1.12.2": + resolution: + { + integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==, + } cpu: [riscv64] os: [linux] libc: [musl] - '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': - resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==} + "@unrs/resolver-binding-linux-s390x-gnu@1.12.2": + resolution: + { + integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==, + } cpu: [s390x] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-x64-gnu@1.12.2': - resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==} + "@unrs/resolver-binding-linux-x64-gnu@1.12.2": + resolution: + { + integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==, + } cpu: [x64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-x64-musl@1.12.2': - resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==} + "@unrs/resolver-binding-linux-x64-musl@1.12.2": + resolution: + { + integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==, + } cpu: [x64] os: [linux] libc: [musl] - '@unrs/resolver-binding-openharmony-arm64@1.12.2': - resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==} + "@unrs/resolver-binding-openharmony-arm64@1.12.2": + resolution: + { + integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==, + } cpu: [arm64] os: [openharmony] - '@unrs/resolver-binding-wasm32-wasi@1.12.2': - resolution: {integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==} - engines: {node: '>=14.0.0'} + "@unrs/resolver-binding-wasm32-wasi@1.12.2": + resolution: + { + integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==, + } + engines: { node: ">=14.0.0" } cpu: [wasm32] - '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': - resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==} + "@unrs/resolver-binding-win32-arm64-msvc@1.12.2": + resolution: + { + integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==, + } cpu: [arm64] os: [win32] - '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': - resolution: {integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==} + "@unrs/resolver-binding-win32-ia32-msvc@1.12.2": + resolution: + { + integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==, + } cpu: [ia32] os: [win32] - '@unrs/resolver-binding-win32-x64-msvc@1.12.2': - resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==} + "@unrs/resolver-binding-win32-x64-msvc@1.12.2": + resolution: + { + integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==, + } cpu: [x64] os: [win32] - '@wagmi/connectors@6.2.0': - resolution: {integrity: sha512-2NfkbqhNWdjfibb4abRMrn7u6rPjEGolMfApXss6HCDVt9AW2oVC6k8Q5FouzpJezElxLJSagWz9FW1zaRlanA==} + "@wagmi/connectors@6.2.0": + resolution: + { + integrity: sha512-2NfkbqhNWdjfibb4abRMrn7u6rPjEGolMfApXss6HCDVt9AW2oVC6k8Q5FouzpJezElxLJSagWz9FW1zaRlanA==, + } peerDependencies: - '@wagmi/core': 2.22.1 - typescript: '>=5.0.4' + "@wagmi/core": 2.22.1 + typescript: ">=5.0.4" viem: 2.x peerDependenciesMeta: typescript: optional: true - '@wagmi/core@2.22.1': - resolution: {integrity: sha512-cG/xwQWsBEcKgRTkQVhH29cbpbs/TdcUJVFXCyri3ZknxhMyGv0YEjTcrNpRgt2SaswL1KrvslSNYKKo+5YEAg==} + "@wagmi/core@2.22.1": + resolution: + { + integrity: sha512-cG/xwQWsBEcKgRTkQVhH29cbpbs/TdcUJVFXCyri3ZknxhMyGv0YEjTcrNpRgt2SaswL1KrvslSNYKKo+5YEAg==, + } peerDependencies: - '@tanstack/query-core': '>=5.0.0' - typescript: '>=5.0.4' + "@tanstack/query-core": ">=5.0.0" + typescript: ">=5.0.4" viem: 2.x peerDependenciesMeta: - '@tanstack/query-core': + "@tanstack/query-core": optional: true typescript: optional: true - '@walletconnect/core@2.21.0': - resolution: {integrity: sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw==} - engines: {node: '>=18'} - - '@walletconnect/core@2.21.1': - resolution: {integrity: sha512-Tp4MHJYcdWD846PH//2r+Mu4wz1/ZU/fr9av1UWFiaYQ2t2TPLDiZxjLw54AAEpMqlEHemwCgiRiAmjR1NDdTQ==} - engines: {node: '>=18'} - - '@walletconnect/environment@1.0.1': - resolution: {integrity: sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==} - - '@walletconnect/ethereum-provider@2.21.1': - resolution: {integrity: sha512-SSlIG6QEVxClgl1s0LMk4xr2wg4eT3Zn/Hb81IocyqNSGfXpjtawWxKxiC5/9Z95f1INyBD6MctJbL/R1oBwIw==} - deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' - - '@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==} + "@walletconnect/core@2.21.0": + resolution: + { + integrity: sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw==, + } + engines: { node: ">=18" } + + "@walletconnect/core@2.21.1": + resolution: + { + integrity: sha512-Tp4MHJYcdWD846PH//2r+Mu4wz1/ZU/fr9av1UWFiaYQ2t2TPLDiZxjLw54AAEpMqlEHemwCgiRiAmjR1NDdTQ==, + } + engines: { node: ">=18" } + + "@walletconnect/environment@1.0.1": + resolution: + { + integrity: sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==, + } + + "@walletconnect/ethereum-provider@2.21.1": + resolution: + { + integrity: sha512-SSlIG6QEVxClgl1s0LMk4xr2wg4eT3Zn/Hb81IocyqNSGfXpjtawWxKxiC5/9Z95f1INyBD6MctJbL/R1oBwIw==, + } + deprecated: "Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases" + + "@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 + "@react-native-async-storage/async-storage": 1.x peerDependenciesMeta: - '@react-native-async-storage/async-storage': + "@react-native-async-storage/async-storage": optional: true - '@walletconnect/logger@2.1.2': - resolution: {integrity: sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==} - - '@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.21.0': - resolution: {integrity: sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA==} - deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' - - '@walletconnect/sign-client@2.21.1': - resolution: {integrity: sha512-QaXzmPsMnKGV6tc4UcdnQVNOz4zyXgarvdIQibJ4L3EmLat73r5ZVl4c0cCOcoaV7rgM9Wbphgu5E/7jNcd3Zg==} - deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' - - '@walletconnect/time@1.0.2': - resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} - - '@walletconnect/types@2.21.0': - resolution: {integrity: sha512-ll+9upzqt95ZBWcfkOszXZkfnpbJJ2CmxMfGgE5GmhdxxxCcO5bGhXkI+x8OpiS555RJ/v/sXJYMSOLkmu4fFw==} - - '@walletconnect/types@2.21.1': - resolution: {integrity: sha512-UeefNadqP6IyfwWC1Yi7ux+ljbP2R66PLfDrDm8izmvlPmYlqRerJWJvYO4t0Vvr9wrG4Ko7E0c4M7FaPKT/sQ==} - - '@walletconnect/universal-provider@2.21.0': - resolution: {integrity: sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg==} - deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' - - '@walletconnect/universal-provider@2.21.1': - resolution: {integrity: sha512-Wjx9G8gUHVMnYfxtasC9poGm8QMiPCpXpbbLFT+iPoQskDDly8BwueWnqKs4Mx2SdIAWAwuXeZ5ojk5qQOxJJg==} - deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' - - '@walletconnect/utils@2.21.0': - resolution: {integrity: sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig==} - - '@walletconnect/utils@2.21.1': - resolution: {integrity: sha512-VPZvTcrNQCkbGOjFRbC24mm/pzbRMUq2DSQoiHlhh0X1U7ZhuIrzVtAoKsrzu6rqjz0EEtGxCr3K1TGRqDG4NA==} - - '@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==} + "@walletconnect/logger@2.1.2": + resolution: + { + integrity: sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==, + } + + "@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.21.0": + resolution: + { + integrity: sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA==, + } + deprecated: "Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases" + + "@walletconnect/sign-client@2.21.1": + resolution: + { + integrity: sha512-QaXzmPsMnKGV6tc4UcdnQVNOz4zyXgarvdIQibJ4L3EmLat73r5ZVl4c0cCOcoaV7rgM9Wbphgu5E/7jNcd3Zg==, + } + deprecated: "Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases" + + "@walletconnect/time@1.0.2": + resolution: + { + integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==, + } + + "@walletconnect/types@2.21.0": + resolution: + { + integrity: sha512-ll+9upzqt95ZBWcfkOszXZkfnpbJJ2CmxMfGgE5GmhdxxxCcO5bGhXkI+x8OpiS555RJ/v/sXJYMSOLkmu4fFw==, + } + + "@walletconnect/types@2.21.1": + resolution: + { + integrity: sha512-UeefNadqP6IyfwWC1Yi7ux+ljbP2R66PLfDrDm8izmvlPmYlqRerJWJvYO4t0Vvr9wrG4Ko7E0c4M7FaPKT/sQ==, + } + + "@walletconnect/universal-provider@2.21.0": + resolution: + { + integrity: sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg==, + } + deprecated: "Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases" + + "@walletconnect/universal-provider@2.21.1": + resolution: + { + integrity: sha512-Wjx9G8gUHVMnYfxtasC9poGm8QMiPCpXpbbLFT+iPoQskDDly8BwueWnqKs4Mx2SdIAWAwuXeZ5ojk5qQOxJJg==, + } + deprecated: "Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases" + + "@walletconnect/utils@2.21.0": + resolution: + { + integrity: sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig==, + } + + "@walletconnect/utils@2.21.1": + resolution: + { + integrity: sha512-VPZvTcrNQCkbGOjFRbC24mm/pzbRMUq2DSQoiHlhh0X1U7ZhuIrzVtAoKsrzu6rqjz0EEtGxCr3K1TGRqDG4NA==, + } + + "@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==, + } abitype@1.0.6: - resolution: {integrity: sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==} + resolution: + { + integrity: sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" zod: ^3 >=3.22.0 peerDependenciesMeta: typescript: @@ -2931,9 +4676,12 @@ packages: optional: true abitype@1.0.8: - resolution: {integrity: sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==} + resolution: + { + integrity: sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" zod: ^3 >=3.22.0 peerDependenciesMeta: typescript: @@ -2942,9 +4690,12 @@ packages: optional: true abitype@1.1.0: - resolution: {integrity: sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==} + resolution: + { + integrity: sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" zod: ^3.22.0 || ^4.0.0 peerDependenciesMeta: typescript: @@ -2953,9 +4704,12 @@ packages: optional: true abitype@1.2.3: - resolution: {integrity: sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==} + resolution: + { + integrity: sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" zod: ^3.22.0 || ^4.0.0 peerDependenciesMeta: typescript: @@ -2964,9 +4718,12 @@ packages: optional: true abitype@1.2.4: - resolution: {integrity: sha512-dpKH+N27vRjarMVTFFkeY445VTKftzGWpL0FiT7xmVmzQRKazZexzC5uHG0f6XKsVLAuUlndnbGau6lRejClxg==} + resolution: + { + integrity: sha512-dpKH+N27vRjarMVTFFkeY445VTKftzGWpL0FiT7xmVmzQRKazZexzC5uHG0f6XKsVLAuUlndnbGau6lRejClxg==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" zod: ^3.22.0 || ^4.0.0 peerDependenciesMeta: typescript: @@ -2975,40 +4732,67 @@ packages: optional: true accepts@2.0.0: - resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==, + } + engines: { node: ">= 0.6" } acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + resolution: + { + integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, + } peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 acorn-walk@8.3.5: - resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} - engines: {node: '>=0.4.0'} + resolution: + { + integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==, + } + engines: { node: ">=0.4.0" } acorn@8.17.0: - resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} - engines: {node: '>=0.4.0'} + resolution: + { + integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==, + } + engines: { node: ">=0.4.0" } hasBin: true aes-js@4.0.0-beta.5: - resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + resolution: + { + integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==, + } agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} + resolution: + { + integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==, + } + engines: { node: ">= 6.0.0" } agent-base@7.1.4: - resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==, + } + engines: { node: ">= 14" } agentkeepalive@4.6.0: - resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} - engines: {node: '>= 8.0.0'} + resolution: + { + integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==, + } + engines: { node: ">= 8.0.0" } ajv-formats@3.0.1: - resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + resolution: + { + integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==, + } peerDependencies: ajv: ^8.0.0 peerDependenciesMeta: @@ -3016,792 +4800,1440 @@ packages: optional: true ajv@6.15.0: - resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + resolution: + { + integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==, + } ajv@8.20.0: - resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + resolution: + { + integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==, + } ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, + } + engines: { node: ">=8" } ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==, + } + engines: { node: ">=12" } ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, + } + engines: { node: ">=8" } anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, + } + engines: { node: ">= 8" } arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + resolution: + { + integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==, + } argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + resolution: + { + integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==, + } argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + resolution: + { + integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, + } aria-hidden@1.2.6: - resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==, + } + engines: { node: ">=10" } aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==, + } + engines: { node: ">= 0.4" } array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==, + } + engines: { node: ">= 0.4" } array-includes@3.1.9: - resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==, + } + engines: { node: ">= 0.4" } array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==, + } + engines: { node: ">= 0.4" } array.prototype.findlastindex@1.2.6: - resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==, + } + engines: { node: ">= 0.4" } array.prototype.flat@1.3.3: - resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==, + } + engines: { node: ">= 0.4" } array.prototype.flatmap@1.3.3: - resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==, + } + engines: { node: ">= 0.4" } array.prototype.tosorted@1.1.4: - resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==, + } + engines: { node: ">= 0.4" } arraybuffer.prototype.slice@1.0.4: - resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==, + } + engines: { node: ">= 0.4" } asn1.js@4.10.1: - resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} + resolution: + { + integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==, + } ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + resolution: + { + integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==, + } ast-types@0.16.1: - resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==, + } + engines: { node: ">=4" } astring@1.9.0: - resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} + resolution: + { + integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==, + } hasBin: true async-function@1.0.0: - resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==, + } + engines: { node: ">= 0.4" } async-mutex@0.2.6: - resolution: {integrity: sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==} + resolution: + { + integrity: sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==, + } asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + 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'} + resolution: + { + integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==, + } + engines: { node: ">=8.0.0" } available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==, + } + engines: { node: ">= 0.4" } axe-core@4.12.1: - resolution: {integrity: sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==, + } + engines: { node: ">=4" } axios-retry@4.5.0: - resolution: {integrity: sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==} + resolution: + { + integrity: sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==, + } peerDependencies: - axios: '>=1.15.0' + axios: ">=1.15.0" axios@1.18.1: - resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} + resolution: + { + integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==, + } axobject-query@4.1.0: - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==, + } + engines: { node: ">= 0.4" } babel-plugin-styled-components@2.3.0: - resolution: {integrity: sha512-nP/y6PbBqS/qtKROnJCgpGo8hYUzlBAVXN1QAjSBANL6vZiQXPQN7FYW/nUwoxY7nZhBEGm9T5tjL9gbzwulDw==} + resolution: + { + integrity: sha512-nP/y6PbBqS/qtKROnJCgpGo8hYUzlBAVXN1QAjSBANL6vZiQXPQN7FYW/nUwoxY7nZhBEGm9T5tjL9gbzwulDw==, + } peerDependencies: - '@babel/core': ^7.0.0 - styled-components: '>= 2' + "@babel/core": ^7.0.0 + styled-components: ">= 2" bail@2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + resolution: + { + integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==, + } balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, + } balanced-match@4.0.4: - resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} - engines: {node: 18 || 20 || >=22} + resolution: + { + integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==, + } + engines: { node: 18 || 20 || >=22 } base-x@3.0.11: - resolution: {integrity: sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==} + resolution: + { + integrity: sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==, + } base-x@5.0.1: - resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} + resolution: + { + integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==, + } base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + resolution: + { + integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, + } baseline-browser-mapping@2.10.40: - resolution: {integrity: sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==} - engines: {node: '>=6.0.0'} + resolution: + { + integrity: sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==, + } + engines: { node: ">=6.0.0" } hasBin: true big.js@6.2.2: - resolution: {integrity: sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==} + resolution: + { + integrity: sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==, + } bl@5.1.0: - resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + resolution: + { + integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==, + } bn.js@4.12.4: - resolution: {integrity: sha512-njR1b+ixG2ufvL9Zn9JGneW+b5GV6jqpYyPPpg4QVt723b5kJPGUczkUyWEH9BwEA74UakJZ43I4FDLBF7ci0g==} + resolution: + { + integrity: sha512-njR1b+ixG2ufvL9Zn9JGneW+b5GV6jqpYyPPpg4QVt723b5kJPGUczkUyWEH9BwEA74UakJZ43I4FDLBF7ci0g==, + } bn.js@5.2.4: - resolution: {integrity: sha512-QL7sb18rJ1PbdsKsqPA0guxL563vIMwRHgzNrW/uzQuRGN1Cjqd/wonUBAVqHox9KwzHA6vCbM0lXx3k4iQMow==} + resolution: + { + integrity: sha512-QL7sb18rJ1PbdsKsqPA0guxL563vIMwRHgzNrW/uzQuRGN1Cjqd/wonUBAVqHox9KwzHA6vCbM0lXx3k4iQMow==, + } body-parser@2.3.0: - resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==, + } + engines: { node: ">=18" } borsh@0.7.0: - resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} + resolution: + { + integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==, + } bowser@2.14.1: - resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} + resolution: + { + integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==, + } brace-expansion@1.1.15: - resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} + resolution: + { + integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==, + } brace-expansion@2.1.1: - resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} + resolution: + { + integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==, + } brace-expansion@5.0.7: - resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} - engines: {node: 18 || 20 || >=22} + resolution: + { + integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==, + } + engines: { node: 18 || 20 || >=22 } braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==, + } + engines: { node: ">=8" } brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + resolution: + { + integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==, + } browserify-aes@1.2.0: - resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + resolution: + { + integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==, + } browserify-cipher@1.0.1: - resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + resolution: + { + integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==, + } browserify-des@1.0.2: - resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + resolution: + { + integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==, + } browserify-rsa@4.1.1: - resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==, + } + engines: { node: ">= 0.10" } browserify-sign@4.2.6: - resolution: {integrity: sha512-sd+Q65fjlWCYWtZKXiKfrUc8d+4jtp/8f0W2NkwzLtoW4bI6UDnWusLWIurHnmurW0XShIRxpwiOX4EoPtXUAg==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-sd+Q65fjlWCYWtZKXiKfrUc8d+4jtp/8f0W2NkwzLtoW4bI6UDnWusLWIurHnmurW0XShIRxpwiOX4EoPtXUAg==, + } + engines: { node: ">= 0.10" } browserslist@4.28.4: - resolution: {integrity: sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + resolution: + { + integrity: sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==, + } + engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } hasBin: true bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + resolution: + { + integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==, + } bs58@6.0.0: - resolution: {integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==} + resolution: + { + integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==, + } buffer-xor@1.0.3: - resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + resolution: + { + integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==, + } buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + resolution: + { + integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==, + } bufferutil@4.1.0: - resolution: {integrity: sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==} - engines: {node: '>=6.14.2'} + resolution: + { + integrity: sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==, + } + engines: { node: ">=6.14.2" } bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, + } + engines: { node: ">= 0.8" } call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, + } + engines: { node: ">= 0.4" } call-bind@1.0.9: - resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==, + } + engines: { node: ">= 0.4" } call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, + } + engines: { node: ">= 0.4" } callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, + } + engines: { node: ">=6" } camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==, + } + engines: { node: ">=6" } camelize@1.0.1: - resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} + resolution: + { + integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==, + } caniuse-lite@1.0.30001800: - resolution: {integrity: sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==} + resolution: + { + integrity: sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==, + } ccount@2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + resolution: + { + integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==, + } chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, + } + engines: { node: ">=10" } chalk@5.6.2: - resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + resolution: + { + integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==, + } + engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } character-entities-html4@2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + resolution: + { + integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==, + } character-entities-legacy@3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + resolution: + { + integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==, + } character-entities@2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + resolution: + { + integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==, + } character-reference-invalid@2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + resolution: + { + integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==, + } charenc@0.0.2: - resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + resolution: + { + integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==, + } chokidar@4.0.3: - resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} - engines: {node: '>= 14.16.0'} + resolution: + { + integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==, + } + engines: { node: ">= 14.16.0" } chokidar@5.0.0: - resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} - engines: {node: '>= 20.19.0'} + resolution: + { + integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==, + } + engines: { node: ">= 20.19.0" } cipher-base@1.0.7: - resolution: {integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==, + } + engines: { node: ">= 0.10" } class-variance-authority@0.7.1: - resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + resolution: + { + integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==, + } cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==, + } + engines: { node: ">=6" } cli-width@4.1.0: - resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} - engines: {node: '>= 12'} + resolution: + { + integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==, + } + engines: { node: ">= 12" } client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + resolution: + { + integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==, + } cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + resolution: + { + integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==, + } cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, + } + engines: { node: ">=12" } clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} + resolution: + { + integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==, + } + engines: { node: ">=0.8" } clsx@1.2.1: - resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==, + } + engines: { node: ">=6" } clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==, + } + engines: { node: ">=6" } code-block-writer@12.0.0: - resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} + resolution: + { + integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==, + } collapse-white-space@2.1.0: - resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} + resolution: + { + integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==, + } color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + 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==} + resolution: + { + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, + } colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + resolution: + { + integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==, + } combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==, + } + engines: { node: ">= 0.8" } comma-separated-tokens@2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + resolution: + { + integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==, + } commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} + resolution: + { + integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==, + } + engines: { node: ">=14" } commander@14.0.2: - resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==, + } + engines: { node: ">=20" } commander@14.0.3: - resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==, + } + engines: { node: ">=20" } commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + resolution: + { + integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==, + } compute-scroll-into-view@3.1.1: - resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==} + resolution: + { + integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==, + } concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + resolution: + { + integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, + } connectkit@1.9.2: - resolution: {integrity: sha512-ZaYdL2UgHdcVy5j7Cn5C6KUtA5Ev3LEc3mPAzEoH3V3hdu3CdC8jgFTFsgInTXXpsdNpwTEEDPnP245ok7wOYg==} - engines: {node: '>=12.4'} + resolution: + { + integrity: sha512-ZaYdL2UgHdcVy5j7Cn5C6KUtA5Ev3LEc3mPAzEoH3V3hdu3CdC8jgFTFsgInTXXpsdNpwTEEDPnP245ok7wOYg==, + } + engines: { node: ">=12.4" } peerDependencies: - '@tanstack/react-query': '>=5.0.0' + "@tanstack/react-query": ">=5.0.0" react: 17.x || 18.x react-dom: 17.x || 18.x viem: 2.x wagmi: 2.x content-disposition@1.1.0: - resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==, + } + engines: { node: ">=18" } content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==, + } + engines: { node: ">= 0.6" } content-type@2.0.0: - resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==, + } + engines: { node: ">=18" } convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + resolution: + { + integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, + } cookie-es@1.2.3: - resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} + resolution: + { + integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==, + } cookie-signature@1.2.2: - resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} - engines: {node: '>=6.6.0'} + resolution: + { + integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==, + } + engines: { node: ">=6.6.0" } cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==, + } + engines: { node: ">= 0.6" } cookie@1.1.1: - resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==, + } + engines: { node: ">=18" } core-js@3.49.0: - resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==} + resolution: + { + integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==, + } core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + resolution: + { + integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, + } cors@2.8.6: - resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==, + } + engines: { node: ">= 0.10" } cosmiconfig@8.3.6: - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} + resolution: + { + integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==, + } + engines: { node: ">=14" } peerDependencies: - typescript: '>=4.9.5' + typescript: ">=4.9.5" peerDependenciesMeta: typescript: optional: true crc-32@1.2.2: - resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} - engines: {node: '>=0.8'} + resolution: + { + integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==, + } + engines: { node: ">=0.8" } hasBin: true create-ecdh@4.0.4: - resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + resolution: + { + integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==, + } create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + resolution: + { + integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==, + } create-hmac@1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + resolution: + { + integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==, + } create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + resolution: + { + integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==, + } cross-fetch@3.2.0: - resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + resolution: + { + integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==, + } cross-fetch@4.1.0: - resolution: {integrity: sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==} + resolution: + { + integrity: sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==, + } cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, + } + engines: { node: ">= 8" } crossws@0.3.5: - resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} + resolution: + { + integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==, + } crypt@0.0.2: - resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + resolution: + { + integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==, + } crypto-browserify@3.12.1: - resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==, + } + engines: { node: ">= 0.10" } css-color-keywords@1.0.0: - resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==, + } + engines: { node: ">=4" } css-to-react-native@3.2.0: - resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} + resolution: + { + integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==, + } csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + resolution: + { + integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==, + } damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + resolution: + { + integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==, + } data-uri-to-buffer@4.0.1: - resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} - engines: {node: '>= 12'} + resolution: + { + integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==, + } + engines: { node: ">= 12" } data-view-buffer@1.0.2: - resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==, + } + engines: { node: ">= 0.4" } data-view-byte-length@1.0.2: - resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==, + } + engines: { node: ">= 0.4" } data-view-byte-offset@1.0.1: - resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==, + } + engines: { node: ">= 0.4" } date-fns@2.30.0: - resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} - engines: {node: '>=0.11'} + resolution: + { + integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==, + } + engines: { node: ">=0.11" } dateformat@4.6.3: - resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + resolution: + { + integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==, + } dayjs@1.11.13: - resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + resolution: + { + integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==, + } debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + resolution: + { + integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==, + } peerDependencies: - supports-color: '*' + supports-color: "*" peerDependenciesMeta: supports-color: optional: true debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} + resolution: + { + integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==, + } + engines: { node: ">=6.0" } peerDependencies: - supports-color: '*' + supports-color: "*" peerDependenciesMeta: supports-color: optional: true debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} + resolution: + { + integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, + } + engines: { node: ">=6.0" } peerDependencies: - supports-color: '*' + supports-color: "*" peerDependenciesMeta: supports-color: optional: true decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==, + } + engines: { node: ">=0.10.0" } decimal.js@10.6.0: - resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + resolution: + { + integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==, + } decode-named-character-reference@1.3.0: - resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + resolution: + { + integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==, + } decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} + resolution: + { + integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==, + } + engines: { node: ">=0.10" } deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + resolution: + { + integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, + } deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==, + } + engines: { node: ">=0.10.0" } defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + resolution: + { + integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==, + } define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, + } + engines: { node: ">= 0.4" } define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==, + } + engines: { node: ">= 0.4" } defu@6.1.7: - resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + resolution: + { + integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==, + } delay@5.0.0: - resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==, + } + engines: { node: ">=10" } delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} + resolution: + { + integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==, + } + engines: { node: ">=0.4.0" } depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, + } + engines: { node: ">= 0.8" } dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==, + } + engines: { node: ">=6" } derive-valtio@0.1.0: - resolution: {integrity: sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==} + resolution: + { + integrity: sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==, + } peerDependencies: - valtio: '*' + valtio: "*" des.js@1.1.0: - resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + resolution: + { + integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==, + } destr@2.0.5: - resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + resolution: + { + integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==, + } detect-browser@5.3.0: - resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} + resolution: + { + integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==, + } + + detect-libc@1.0.3: + resolution: + { + integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==, + } + engines: { node: ">=0.10" } + hasBin: true detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==, + } + engines: { node: ">=8" } detect-node-es@1.1.0: - resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + resolution: + { + integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==, + } devlop@1.1.0: - resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + resolution: + { + integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==, + } diff@4.0.4: - resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} - engines: {node: '>=0.3.1'} + resolution: + { + integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==, + } + engines: { node: ">=0.3.1" } diff@5.2.2: - resolution: {integrity: sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==} - engines: {node: '>=0.3.1'} + resolution: + { + integrity: sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==, + } + engines: { node: ">=0.3.1" } diffie-hellman@5.0.3: - resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + resolution: + { + integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==, + } dijkstrajs@1.0.3: - resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + resolution: + { + integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==, + } doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==, + } + engines: { node: ">=0.10.0" } dompurify@3.4.11: - resolution: {integrity: sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==} + resolution: + { + integrity: sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==, + } dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, + } + engines: { node: ">= 0.4" } duplexify@4.1.3: - resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} + resolution: + { + integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==, + } eciesjs@0.4.18: - resolution: {integrity: sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ==} - engines: {bun: '>=1', deno: '>=2', node: '>=16'} + resolution: + { + integrity: sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ==, + } + engines: { bun: ">=1", deno: ">=2", node: ">=16" } ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + resolution: + { + integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, + } electron-to-chromium@1.5.384: - resolution: {integrity: sha512-g6KAKY1vkYsADvSPWvdJsuYT0ixdcu6lUtD9P/wJKGBEDlZVXh2AX42j1mPqqaQPDluWjara9ziQ7xqAeXCt5A==} + resolution: + { + integrity: sha512-g6KAKY1vkYsADvSPWvdJsuYT0ixdcu6lUtD9P/wJKGBEDlZVXh2AX42j1mPqqaQPDluWjara9ziQ7xqAeXCt5A==, + } elliptic@6.6.1: - resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + resolution: + { + integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==, + } emoji-regex-xs@1.0.0: - resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + resolution: + { + integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==, + } emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, + } emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + resolution: + { + integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, + } encode-utf8@1.0.3: - resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + resolution: + { + integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==, + } encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==, + } + engines: { node: ">= 0.8" } end-of-stream@1.4.5: - resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + resolution: + { + integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==, + } engine.io-client@6.6.6: - resolution: {integrity: sha512-iY6QdftLQ9pyiPoX082bpf/u1UewnOaJrtJIF9T0++QB34lZrj0uP+Q/bj8AlUsAxqhnkTV2BS8SBZSxOmoV5Q==} + resolution: + { + integrity: sha512-iY6QdftLQ9pyiPoX082bpf/u1UewnOaJrtJIF9T0++QB34lZrj0uP+Q/bj8AlUsAxqhnkTV2BS8SBZSxOmoV5Q==, + } engine.io-parser@5.2.3: - resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==, + } + engines: { node: ">=10.0.0" } enhanced-resolve@5.21.6: - resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} - engines: {node: '>=10.13.0'} + resolution: + { + integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==, + } + engines: { node: ">=10.13.0" } + + enhanced-resolve@5.25.1: + resolution: + { + integrity: sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w==, + } + engines: { node: ">=10.13.0" } entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} + resolution: + { + integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==, + } + engines: { node: ">=0.12" } error-ex@1.3.4: - resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + resolution: + { + integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==, + } es-abstract-get@1.0.0: - resolution: {integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==, + } + engines: { node: ">= 0.4" } es-abstract@1.24.2: - resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==, + } + engines: { node: ">= 0.4" } es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, + } + engines: { node: ">= 0.4" } es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, + } + engines: { node: ">= 0.4" } es-iterator-helpers@1.3.3: - resolution: {integrity: sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==, + } + engines: { node: ">= 0.4" } es-object-atoms@1.1.2: - resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} - engines: {node: '>= 0.4'} + 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'} + resolution: + { + integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, + } + engines: { node: ">= 0.4" } es-shim-unscopables@1.1.0: - resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==, + } + engines: { node: ">= 0.4" } es-to-primitive@1.3.4: - resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==, + } + engines: { node: ">= 0.4" } es-toolkit@1.33.0: - resolution: {integrity: sha512-X13Q/ZSc+vsO1q600bvNK4bxgXMkHcf//RxCmYDaRY5DAcT+eoXjY5hoAPGMdRnWQjvyLEcyauG3b6hz76LNqg==} + resolution: + { + integrity: sha512-X13Q/ZSc+vsO1q600bvNK4bxgXMkHcf//RxCmYDaRY5DAcT+eoXjY5hoAPGMdRnWQjvyLEcyauG3b6hz76LNqg==, + } es-toolkit@1.46.1: - resolution: {integrity: sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==} + resolution: + { + integrity: sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==, + } es6-promise@4.2.8: - resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + resolution: + { + integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==, + } es6-promisify@5.0.0: - resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} + resolution: + { + integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==, + } esast-util-from-estree@2.0.0: - resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} + resolution: + { + integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==, + } esast-util-from-js@2.0.1: - resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} + resolution: + { + integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==, + } esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==, + } + engines: { node: ">=18" } hasBin: true esbuild@0.28.1: - resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==, + } + engines: { node: ">=18" } hasBin: true escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, + } + engines: { node: ">=6" } escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + resolution: + { + integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, + } escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, + } + engines: { node: ">=10" } escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==, + } + engines: { node: ">=12" } eslint-config-next@16.2.3: - resolution: {integrity: sha512-Dnkrylzjof/Az7iNoIQJqD18zTxQZcngir19KJaiRsMnnjpQSVoa6aEg/1Q4hQC+cW90uTlgQYadwL1CYNwFWA==} + resolution: + { + integrity: sha512-Dnkrylzjof/Az7iNoIQJqD18zTxQZcngir19KJaiRsMnnjpQSVoa6aEg/1Q4hQC+cW90uTlgQYadwL1CYNwFWA==, + } peerDependencies: - eslint: '>=9.0.0' - typescript: '>=3.3.1' + eslint: ">=9.0.0" + typescript: ">=3.3.1" peerDependenciesMeta: typescript: optional: true eslint-import-resolver-node@0.3.10: - resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==} + resolution: + { + integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==, + } eslint-import-resolver-typescript@3.10.1: - resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==} - engines: {node: ^14.18.0 || >=16.0.0} + resolution: + { + integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==, + } + engines: { node: ^14.18.0 || >=16.0.0 } peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - eslint-plugin-import-x: '*' + eslint: "*" + eslint-plugin-import: "*" + eslint-plugin-import-x: "*" peerDependenciesMeta: eslint-plugin-import: optional: true @@ -3809,16 +6241,19 @@ packages: optional: true eslint-module-utils@2.13.0: - resolution: {integrity: sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==, + } + engines: { node: ">=4" } peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' + "@typescript-eslint/parser": "*" + eslint: "*" + eslint-import-resolver-node: "*" + eslint-import-resolver-typescript: "*" + eslint-import-resolver-webpack: "*" peerDependenciesMeta: - '@typescript-eslint/parser': + "@typescript-eslint/parser": optional: true eslint: optional: true @@ -3830,231 +6265,405 @@ packages: optional: true eslint-plugin-import@2.32.0: - resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==, + } + engines: { node: ">=4" } peerDependencies: - '@typescript-eslint/parser': '*' + "@typescript-eslint/parser": "*" eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 peerDependenciesMeta: - '@typescript-eslint/parser': + "@typescript-eslint/parser": optional: true eslint-plugin-jsx-a11y@6.10.2: - resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} - engines: {node: '>=4.0'} + resolution: + { + integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==, + } + engines: { node: ">=4.0" } peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 eslint-plugin-react-hooks@7.1.1: - resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==, + } + engines: { node: ">=18" } peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0 eslint-plugin-react@7.37.5: - resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==, + } + engines: { node: ">=4" } peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 eslint-scope@8.4.0: - resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + resolution: + { + integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + resolution: + { + integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } eslint-visitor-keys@4.2.1: - resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + resolution: + { + integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } eslint-visitor-keys@5.0.1: - resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + resolution: + { + integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==, + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } eslint@9.39.4: - resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + resolution: + { + integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true peerDependencies: - jiti: '*' + jiti: "*" peerDependenciesMeta: jiti: optional: true espree@10.4.0: - resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + resolution: + { + integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, + } + engines: { node: ">=4" } hasBin: true esquery@1.7.0: - resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} - engines: {node: '>=0.10'} + resolution: + { + integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==, + } + engines: { node: ">=0.10" } esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} + resolution: + { + integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, + } + engines: { node: ">=4.0" } estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} + resolution: + { + integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, + } + engines: { node: ">=4.0" } estree-util-attach-comments@3.0.0: - resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==} + resolution: + { + integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==, + } estree-util-build-jsx@3.0.1: - resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==} + resolution: + { + integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==, + } estree-util-is-identifier-name@3.0.0: - resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + resolution: + { + integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==, + } estree-util-scope@1.0.0: - resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==} + resolution: + { + integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==, + } estree-util-to-js@2.0.0: - resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} + resolution: + { + integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==, + } estree-util-value-to-estree@3.5.0: - resolution: {integrity: sha512-aMV56R27Gv3QmfmF1MY12GWkGzzeAezAX+UplqHVASfjc9wNzI/X6hC0S9oxq61WT4aQesLGslWP9tKk6ghRZQ==} + resolution: + { + integrity: sha512-aMV56R27Gv3QmfmF1MY12GWkGzzeAezAX+UplqHVASfjc9wNzI/X6hC0S9oxq61WT4aQesLGslWP9tKk6ghRZQ==, + } estree-util-visit@2.0.0: - resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + resolution: + { + integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==, + } estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + resolution: + { + integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==, + } esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, + } + engines: { node: ">=0.10.0" } etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==, + } + engines: { node: ">= 0.6" } eth-block-tracker@7.1.0: - resolution: {integrity: sha512-8YdplnuE1IK4xfqpf4iU7oBxnOYAc35934o083G8ao+8WM8QQtt/mVlAY6yIAdY1eMeLqg4Z//PZjJGmWGPMRg==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-8YdplnuE1IK4xfqpf4iU7oBxnOYAc35934o083G8ao+8WM8QQtt/mVlAY6yIAdY1eMeLqg4Z//PZjJGmWGPMRg==, + } + engines: { node: ">=14.0.0" } eth-json-rpc-filters@6.0.1: - resolution: {integrity: sha512-ITJTvqoCw6OVMLs7pI8f4gG92n/St6x80ACtHodeS+IXmO0w+t1T5OOzfSt7KLSMLRkVUoexV7tztLgDxg+iig==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-ITJTvqoCw6OVMLs7pI8f4gG92n/St6x80ACtHodeS+IXmO0w+t1T5OOzfSt7KLSMLRkVUoexV7tztLgDxg+iig==, + } + engines: { node: ">=14.0.0" } eth-query@2.1.2: - resolution: {integrity: sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA==} + resolution: + { + integrity: sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA==, + } eth-rpc-errors@4.0.3: - resolution: {integrity: sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg==} + resolution: + { + integrity: sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg==, + } ethereum-cryptography@2.2.1: - resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==} + resolution: + { + integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==, + } ethers@6.17.0: - resolution: {integrity: sha512-BpyrpIPJ3ydEVow8zGaz1DuPS7YU8DcWxuBnY9a0UA/lvAPwrMr+EPXsfrul628SRaekPNeIM4UFh/91GWZang==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-BpyrpIPJ3ydEVow8zGaz1DuPS7YU8DcWxuBnY9a0UA/lvAPwrMr+EPXsfrul628SRaekPNeIM4UFh/91GWZang==, + } + engines: { node: ">=14.0.0" } eventemitter2@6.4.9: - resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==} + resolution: + { + integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==, + } eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + resolution: + { + integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==, + } eventemitter3@5.0.4: - resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + resolution: + { + integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==, + } events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} + resolution: + { + integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==, + } + engines: { node: ">=0.8.x" } eventsource-parser@3.1.0: - resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} - engines: {node: '>=18.0.0'} + resolution: + { + integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==, + } + engines: { node: ">=18.0.0" } eventsource@3.0.7: - resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} - engines: {node: '>=18.0.0'} + resolution: + { + integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==, + } + engines: { node: ">=18.0.0" } evp_bytestokey@1.0.3: - resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + resolution: + { + integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==, + } execa@7.2.0: - resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} - engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} + resolution: + { + integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==, + } + engines: { node: ^14.18.0 || ^16.14.0 || >=18.0.0 } express-rate-limit@8.5.2: - resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} - engines: {node: '>= 16'} + resolution: + { + integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==, + } + engines: { node: ">= 16" } peerDependencies: - express: '>= 4.11' + express: ">= 4.11" express@5.2.1: - resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} - engines: {node: '>= 18'} + resolution: + { + integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==, + } + engines: { node: ">= 18" } extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + resolution: + { + integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==, + } extension-port-stream@3.0.0: - resolution: {integrity: sha512-an2S5quJMiy5bnZKEf6AkfH/7r8CzHvhchU40gxN+OM6HPhe7Z9T1FUychcf2M9PpPOO0Hf7BAEfJkw2TDIBDw==} - engines: {node: '>=12.0.0'} + resolution: + { + integrity: sha512-an2S5quJMiy5bnZKEf6AkfH/7r8CzHvhchU40gxN+OM6HPhe7Z9T1FUychcf2M9PpPOO0Hf7BAEfJkw2TDIBDw==, + } + engines: { node: ">=12.0.0" } eyes@0.1.8: - resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} - engines: {node: '> 0.1.90'} + resolution: + { + integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==, + } + engines: { node: "> 0.1.90" } fast-copy@4.0.3: - resolution: {integrity: sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw==} + resolution: + { + integrity: sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw==, + } fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + resolution: + { + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, + } fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} + resolution: + { + integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==, + } + engines: { node: ">=8.6.0" } fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} + resolution: + { + integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==, + } + engines: { node: ">=8.6.0" } fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + resolution: + { + integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, + } fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + resolution: + { + integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, + } fast-redact@3.5.0: - resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==, + } + engines: { node: ">=6" } fast-safe-stringify@2.1.1: - resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + resolution: + { + integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==, + } fast-stable-stringify@1.0.0: - resolution: {integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==} + resolution: + { + integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==, + } fast-string-truncated-width@3.0.3: - resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==} + resolution: + { + integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==, + } fast-string-width@3.0.2: - resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} + resolution: + { + integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==, + } fast-uri@3.1.3: - resolution: {integrity: sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==} + resolution: + { + integrity: sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==, + } fast-wrap-ansi@0.2.2: - resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + resolution: + { + integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==, + } fastq@1.20.1: - resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + resolution: + { + integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==, + } fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} + resolution: + { + integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==, + } + engines: { node: ">=12.0.0" } peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -4062,132 +6671,198 @@ packages: optional: true fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} + resolution: + { + integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==, + } + engines: { node: ^12.20 || >= 14.13 } fflate@0.4.8: - resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + resolution: + { + integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==, + } file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} + resolution: + { + integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==, + } + engines: { node: ">=16.0.0" } fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, + } + engines: { node: ">=8" } filter-obj@1.1.0: - resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==, + } + engines: { node: ">=0.10.0" } finalhandler@2.1.1: - resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} - engines: {node: '>= 18.0.0'} + resolution: + { + integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==, + } + engines: { node: ">= 18.0.0" } find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==, + } + engines: { node: ">=8" } find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, + } + engines: { node: ">=10" } flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} + resolution: + { + integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==, + } + engines: { node: ">=16" } flatted@3.4.2: - resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + resolution: + { + integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==, + } follow-redirects@1.16.0: - resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} - engines: {node: '>=4.0'} + resolution: + { + integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==, + } + engines: { node: ">=4.0" } peerDependencies: - debug: '*' + debug: "*" peerDependenciesMeta: debug: optional: true for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==, + } + engines: { node: ">= 0.4" } form-data@4.0.6: - resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==, + } + engines: { node: ">= 6" } formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} + resolution: + { + integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==, + } + engines: { node: ">=12.20.0" } forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==, + } + engines: { node: ">= 0.6" } framer-motion@6.5.1: - resolution: {integrity: sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==} + resolution: + { + integrity: sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==, + } peerDependencies: - react: '>=16.8 || ^17.0.0 || ^18.0.0' - react-dom: '>=16.8 || ^17.0.0 || ^18.0.0' + react: ">=16.8 || ^17.0.0 || ^18.0.0" + react-dom: ">=16.8 || ^17.0.0 || ^18.0.0" framesync@6.0.1: - resolution: {integrity: sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==} + resolution: + { + integrity: sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==, + } fresh@2.0.0: - resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==, + } + engines: { node: ">= 0.8" } front-matter@4.0.2: - resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} + resolution: + { + integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==, + } fs-extra@11.3.6: - resolution: {integrity: sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==} - engines: {node: '>=14.14'} + resolution: + { + integrity: sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==, + } + engines: { node: ">=14.14" } fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + resolution: + { + integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, + } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } os: [darwin] fumadocs-core@16.10.7: - resolution: {integrity: sha512-lR1hDOtJ8ubsLKYH2VMkp+iVZTDdOiMh4StFaWtuTvy8Wfnngz0YSHeFijmm2K+4lg2DLXLMuCEHQ6my54g2Eg==} + resolution: + { + integrity: sha512-lR1hDOtJ8ubsLKYH2VMkp+iVZTDdOiMh4StFaWtuTvy8Wfnngz0YSHeFijmm2K+4lg2DLXLMuCEHQ6my54g2Eg==, + } peerDependencies: - '@mdx-js/mdx': '*' - '@mixedbread/sdk': 0.x.x - '@orama/core': 1.x.x - '@oramacloud/client': 2.x.x - '@tanstack/react-router': 1.x.x - '@types/estree-jsx': '*' - '@types/hast': '*' - '@types/mdast': '*' - '@types/react': 19.1.2 + "@mdx-js/mdx": "*" + "@mixedbread/sdk": 0.x.x + "@orama/core": 1.x.x + "@oramacloud/client": 2.x.x + "@tanstack/react-router": 1.x.x + "@types/estree-jsx": "*" + "@types/hast": "*" + "@types/mdast": "*" + "@types/react": 19.1.2 algoliasearch: 5.x.x - flexsearch: '*' - lucide-react: '*' + flexsearch: "*" + lucide-react: "*" next: 16.x.x react: ^19.2.0 react-dom: ^19.2.0 react-router: 7.x.x || 8.x.x - waku: '*' + waku: "*" zod: 4.x.x peerDependenciesMeta: - '@mdx-js/mdx': + "@mdx-js/mdx": optional: true - '@mixedbread/sdk': + "@mixedbread/sdk": optional: true - '@orama/core': + "@orama/core": optional: true - '@oramacloud/client': + "@oramacloud/client": optional: true - '@tanstack/react-router': + "@tanstack/react-router": optional: true - '@types/estree-jsx': + "@types/estree-jsx": optional: true - '@types/hast': + "@types/hast": optional: true - '@types/mdast': + "@types/mdast": optional: true - '@types/react': + "@types/react": optional: true algoliasearch: optional: true @@ -4209,16 +6884,19 @@ packages: optional: true fumadocs-mdx@13.0.8: - resolution: {integrity: sha512-UbUwH0iGvYbytnxhmfd7tWJKFK8L0mrbTAmrQYnpg6Wi/h8afNMJmbHBOzVcaEWJKeFipZ1CGDAsNA2fztwXNg==} + resolution: + { + integrity: sha512-UbUwH0iGvYbytnxhmfd7tWJKFK8L0mrbTAmrQYnpg6Wi/h8afNMJmbHBOzVcaEWJKeFipZ1CGDAsNA2fztwXNg==, + } hasBin: true peerDependencies: - '@fumadocs/mdx-remote': ^1.4.0 + "@fumadocs/mdx-remote": ^1.4.0 fumadocs-core: ^15.0.0 || ^16.0.0 next: ^15.3.0 || ^16.0.0 - react: '*' + react: "*" vite: 6.x.x || 7.x.x peerDependenciesMeta: - '@fumadocs/mdx-remote': + "@fumadocs/mdx-remote": optional: true next: optional: true @@ -4228,1017 +6906,1837 @@ packages: optional: true function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + resolution: + { + integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, + } function.prototype.name@1.2.0: - resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==, + } + engines: { node: ">= 0.4" } functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + resolution: + { + integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==, + } generator-function@2.0.1: - resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==, + } + engines: { node: ">= 0.4" } gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} + 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.*} + 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'} + resolution: + { + integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, + } + engines: { node: ">= 0.4" } get-nonce@1.0.1: - resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==, + } + engines: { node: ">=6" } get-own-enumerable-keys@1.0.0: - resolution: {integrity: sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==, + } + engines: { node: ">=14.16" } get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, + } + engines: { node: ">= 0.4" } get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==, + } + engines: { node: ">=10" } get-symbol-description@1.1.0: - resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==, + } + engines: { node: ">= 0.4" } get-tsconfig@4.14.0: - resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} + resolution: + { + integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==, + } github-slugger@2.0.0: - resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + resolution: + { + integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==, + } glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, + } + engines: { node: ">= 6" } glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + resolution: + { + integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==, + } + engines: { node: ">=10.13.0" } globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==, + } + engines: { node: ">=18" } globals@16.4.0: - resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==, + } + engines: { node: ">=18" } globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==, + } + engines: { node: ">= 0.4" } gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, + } + engines: { node: ">= 0.4" } gql.tada@1.11.2: - resolution: {integrity: sha512-oBr7ShA5/TmcwOO7BZgN1SynX2rBU+/ltysB0zXc+NCBF+9YOg6MRzJcTfLjIqDKdcE3LGxpOl0l9hBbxmyzmA==} + resolution: + { + integrity: sha512-oBr7ShA5/TmcwOO7BZgN1SynX2rBU+/ltysB0zXc+NCBF+9YOg6MRzJcTfLjIqDKdcE3LGxpOl0l9hBbxmyzmA==, + } hasBin: true peerDependencies: typescript: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + resolution: + { + integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==, + } graphql@16.14.2: - resolution: {integrity: sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA==} - engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + resolution: + { + integrity: sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA==, + } + engines: { node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0 } h3@1.15.11: - resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==} + resolution: + { + integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==, + } has-bigints@1.1.0: - resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==, + } + engines: { node: ">= 0.4" } has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, + } + engines: { node: ">=4" } has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, + } + engines: { node: ">=8" } has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + resolution: + { + integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==, + } has-proto@1.2.0: - resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==, + } + engines: { node: ">= 0.4" } has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, + } + engines: { node: ">= 0.4" } has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==, + } + engines: { node: ">= 0.4" } hash-base@3.0.5: - resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==, + } + engines: { node: ">= 0.10" } hash-base@3.1.2: - resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==, + } + engines: { node: ">= 0.8" } hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + resolution: + { + integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==, + } hasown@2.0.4: - resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==, + } + engines: { node: ">= 0.4" } hast-util-from-html@2.0.3: - resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} + resolution: + { + integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==, + } hast-util-from-parse5@8.0.3: - resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==} + resolution: + { + integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==, + } hast-util-parse-selector@4.0.0: - resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + resolution: + { + integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==, + } hast-util-to-estree@3.1.3: - resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==} + resolution: + { + integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==, + } hast-util-to-html@9.0.5: - resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + resolution: + { + integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==, + } hast-util-to-jsx-runtime@2.3.6: - resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} + resolution: + { + integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==, + } hast-util-to-string@3.0.1: - resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==} + resolution: + { + integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==, + } hast-util-whitespace@3.0.0: - resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + resolution: + { + integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==, + } hastscript@9.0.1: - resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} + resolution: + { + integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==, + } headers-polyfill@5.0.1: - resolution: {integrity: sha512-1TJ6Fih/b8h5TIcv+1+Hw0PDQWJTKDKzFZzcKOiW1wJza3XoAQlkCuXLbymPYB8+ZQyw8mHvdw560e8zVFIWyA==} + resolution: + { + integrity: sha512-1TJ6Fih/b8h5TIcv+1+Hw0PDQWJTKDKzFZzcKOiW1wJza3XoAQlkCuXLbymPYB8+ZQyw8mHvdw560e8zVFIWyA==, + } help-me@5.0.0: - resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + resolution: + { + integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==, + } hermes-estree@0.25.1: - resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + resolution: + { + integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==, + } hermes-parser@0.25.1: - resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + resolution: + { + integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==, + } hey-listen@1.0.8: - resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==} + resolution: + { + integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==, + } hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + resolution: + { + integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==, + } hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + resolution: + { + integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==, + } hono@4.12.27: - resolution: {integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==} - engines: {node: '>=16.9.0'} + resolution: + { + integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==, + } + engines: { node: ">=16.9.0" } html-void-elements@3.0.0: - resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + resolution: + { + integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==, + } http-errors@2.0.1: - resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==, + } + engines: { node: ">= 0.8" } https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==, + } + engines: { node: ">= 6" } https-proxy-agent@6.2.1: - resolution: {integrity: sha512-ONsE3+yfZF2caH5+bJlcddtWqNI3Gvs5A38+ngvljxaBiRXRswym2c7yf8UAeFpRFKjFNHIFEHqR/OLAWJzyiA==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-ONsE3+yfZF2caH5+bJlcddtWqNI3Gvs5A38+ngvljxaBiRXRswym2c7yf8UAeFpRFKjFNHIFEHqR/OLAWJzyiA==, + } + engines: { node: ">= 14" } human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} + resolution: + { + integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==, + } + engines: { node: ">=14.18.0" } humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + resolution: + { + integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==, + } iconv-lite@0.7.2: - resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==, + } + engines: { node: ">=0.10.0" } idb-keyval@6.2.1: - resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} + resolution: + { + integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==, + } idb-keyval@6.2.6: - resolution: {integrity: sha512-FY64UEhw+5liMzMQ1R9Mw6AF0+wyBrg1CIA1z4CjI/EvT5ty/SvQcWZgd8s9sgaNhX10Y8UzScTh89tEAls5nA==} + resolution: + { + integrity: sha512-FY64UEhw+5liMzMQ1R9Mw6AF0+wyBrg1CIA1z4CjI/EvT5ty/SvQcWZgd8s9sgaNhX10Y8UzScTh89tEAls5nA==, + } ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + resolution: + { + integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, + } ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==, + } + engines: { node: ">= 4" } ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==, + } + engines: { node: ">= 4" } import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==, + } + engines: { node: ">=6" } imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} + resolution: + { + integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, + } + engines: { node: ">=0.8.19" } inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + resolution: + { + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, + } inline-style-parser@0.2.7: - resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} + resolution: + { + integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==, + } internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==, + } + engines: { node: ">= 0.4" } ip-address@10.2.0: - resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} - engines: {node: '>= 12'} + resolution: + { + integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==, + } + engines: { node: ">= 12" } ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==, + } + engines: { node: ">= 0.10" } iron-webcrypto@1.2.1: - resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + resolution: + { + integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==, + } is-alphabetical@2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + resolution: + { + integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==, + } is-alphanumerical@2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + resolution: + { + integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==, + } is-arguments@1.2.0: - resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==, + } + engines: { node: ">= 0.4" } is-array-buffer@3.0.5: - resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==, + } + engines: { node: ">= 0.4" } is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + resolution: + { + integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, + } is-async-function@2.1.1: - resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==, + } + engines: { node: ">= 0.4" } is-bigint@1.1.0: - resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==, + } + engines: { node: ">= 0.4" } is-boolean-object@1.2.2: - resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==, + } + engines: { node: ">= 0.4" } is-buffer@1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + resolution: + { + integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==, + } is-bun-module@2.0.0: - resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} + resolution: + { + integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==, + } is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==, + } + engines: { node: ">= 0.4" } is-core-module@2.16.2: - resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==, + } + engines: { node: ">= 0.4" } is-data-view@1.0.2: - resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==, + } + engines: { node: ">= 0.4" } is-date-object@1.1.0: - resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==, + } + engines: { node: ">= 0.4" } is-decimal@2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + resolution: + { + integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==, + } is-document.all@1.0.0: - resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==, + } + engines: { node: ">= 0.4" } is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, + } + engines: { node: ">=0.10.0" } is-finalizationregistry@1.1.1: - resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==, + } + engines: { node: ">= 0.4" } is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, + } + engines: { node: ">=8" } is-generator-function@1.1.2: - resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==, + } + engines: { node: ">= 0.4" } is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, + } + engines: { node: ">=0.10.0" } is-hexadecimal@2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + resolution: + { + integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==, + } is-interactive@2.0.0: - resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==, + } + engines: { node: ">=12" } is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==, + } + engines: { node: ">= 0.4" } is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==, + } + engines: { node: ">= 0.4" } is-node-process@1.2.0: - resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + resolution: + { + integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==, + } is-number-object@1.1.1: - resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==, + } + engines: { node: ">= 0.4" } is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} + resolution: + { + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, + } + engines: { node: ">=0.12.0" } is-obj@3.0.0: - resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==, + } + engines: { node: ">=12" } is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==, + } + engines: { node: ">=12" } is-promise@4.0.0: - resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + resolution: + { + integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==, + } is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==, + } + engines: { node: ">= 0.4" } is-regexp@3.1.0: - resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==, + } + engines: { node: ">=12" } is-retry-allowed@2.2.0: - resolution: {integrity: sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==, + } + engines: { node: ">=10" } is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==, + } + engines: { node: ">= 0.4" } is-shared-array-buffer@1.0.4: - resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==, + } + engines: { node: ">= 0.4" } is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==, + } + engines: { node: ">=8" } is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } is-string@1.1.1: - resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==, + } + engines: { node: ">= 0.4" } is-symbol@1.1.1: - resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==, + } + engines: { node: ">= 0.4" } is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==, + } + engines: { node: ">= 0.4" } is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==, + } + engines: { node: ">=12" } is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==, + } + engines: { node: ">= 0.4" } is-weakref@1.1.1: - resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==, + } + engines: { node: ">= 0.4" } is-weakset@2.0.4: - resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==, + } + engines: { node: ">= 0.4" } isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + resolution: + { + integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==, + } isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + resolution: + { + integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==, + } isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + resolution: + { + integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, + } isomorphic-ws@4.0.1: - resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} + resolution: + { + integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==, + } peerDependencies: - ws: '*' + ws: "*" isows@1.0.6: - resolution: {integrity: sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==} + resolution: + { + integrity: sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==, + } peerDependencies: - ws: '*' + ws: "*" isows@1.0.7: - resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==} + resolution: + { + integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==, + } peerDependencies: - ws: '*' + ws: "*" iterator.prototype@1.1.5: - resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==, + } + engines: { node: ">= 0.4" } jayson@4.3.0: - resolution: {integrity: sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==, + } + engines: { node: ">=8" } hasBin: true jiti@2.7.0: - resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + resolution: + { + integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==, + } hasBin: true jose@6.2.3: - resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + resolution: + { + integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==, + } joycon@3.1.1: - resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==, + } + engines: { node: ">=10" } js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + resolution: + { + integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==, + } js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + resolution: + { + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, + } js-yaml@3.15.0: - resolution: {integrity: sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==} + resolution: + { + integrity: sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==, + } hasBin: true js-yaml@4.3.0: - resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + resolution: + { + integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==, + } hasBin: true js-yaml@5.2.1: - resolution: {integrity: sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==} + resolution: + { + integrity: sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==, + } hasBin: true jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==, + } + engines: { node: ">=6" } hasBin: true json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + resolution: + { + integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, + } json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + resolution: + { + integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, + } json-rpc-engine@6.1.0: - resolution: {integrity: sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ==, + } + engines: { node: ">=10.0.0" } json-rpc-random-id@1.0.1: - resolution: {integrity: sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA==} + resolution: + { + integrity: sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA==, + } json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + resolution: + { + integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, + } json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + resolution: + { + integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, + } json-schema-typed@8.0.2: - resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + resolution: + { + integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==, + } json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + resolution: + { + integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, + } json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + resolution: + { + integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==, + } json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + resolution: + { + integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==, + } hasBin: true json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, + } + engines: { node: ">=6" } hasBin: true jsonfile@6.2.1: - resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + resolution: + { + integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==, + } jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} + resolution: + { + integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==, + } + engines: { node: ">=4.0" } keccak@3.0.4: - resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==, + } + engines: { node: ">=10.0.0" } keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + resolution: + { + integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, + } keyvaluestorage-interface@1.0.0: - resolution: {integrity: sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==} + resolution: + { + integrity: sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==, + } kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==, + } + engines: { node: ">=6" } kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==, + } + engines: { node: ">=6" } language-subtag-registry@0.3.23: - resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + resolution: + { + integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==, + } language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} + resolution: + { + integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==, + } + engines: { node: ">=0.10" } levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + resolution: + { + integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, + } + engines: { node: ">= 0.8.0" } lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==, + } + engines: { node: ">= 12.0.0" } cpu: [arm64] os: [android] lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==, + } + engines: { node: ">= 12.0.0" } cpu: [arm64] os: [darwin] lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==, + } + engines: { node: ">= 12.0.0" } cpu: [x64] os: [darwin] lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==, + } + engines: { node: ">= 12.0.0" } cpu: [x64] os: [freebsd] lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==, + } + engines: { node: ">= 12.0.0" } cpu: [arm] os: [linux] lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==, + } + engines: { node: ">= 12.0.0" } cpu: [arm64] os: [linux] libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==, + } + engines: { node: ">= 12.0.0" } cpu: [arm64] os: [linux] libc: [musl] lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==, + } + engines: { node: ">= 12.0.0" } cpu: [x64] os: [linux] libc: [glibc] lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==, + } + engines: { node: ">= 12.0.0" } cpu: [x64] os: [linux] libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==, + } + engines: { node: ">= 12.0.0" } cpu: [arm64] os: [win32] lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==, + } + engines: { node: ">= 12.0.0" } cpu: [x64] os: [win32] lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==, + } + engines: { node: ">= 12.0.0" } lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + resolution: + { + integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, + } lit-element@4.2.2: - resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} + resolution: + { + integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==, + } lit-html@3.3.3: - resolution: {integrity: sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==} + resolution: + { + integrity: sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==, + } lit@3.3.0: - resolution: {integrity: sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==} + resolution: + { + integrity: sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==, + } locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==, + } + engines: { node: ">=8" } locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, + } + engines: { node: ">=10" } lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + resolution: + { + integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, + } lodash@4.18.1: - resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + resolution: + { + integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==, + } log-symbols@5.1.0: - resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==, + } + engines: { node: ">=12" } longest-streak@3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + resolution: + { + integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==, + } loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + resolution: + { + integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==, + } hasBin: true lru-cache@11.5.1: - resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} - engines: {node: 20 || >=22} + resolution: + { + integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==, + } + engines: { node: 20 || >=22 } lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + resolution: + { + integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==, + } lucide-react@0.487.0: - resolution: {integrity: sha512-aKqhOQ+YmFnwq8dWgGjOuLc8V1R9/c/yOd+zDY4+ohsR2Jo05lSGc3WsstYPIzcTpeosN7LoCkLReUUITvaIvw==} + resolution: + { + integrity: sha512-aKqhOQ+YmFnwq8dWgGjOuLc8V1R9/c/yOd+zDY4+ohsR2Jo05lSGc3WsstYPIzcTpeosN7LoCkLReUUITvaIvw==, + } peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + resolution: + { + integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==, + } make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + resolution: + { + integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==, + } markdown-extensions@2.0.0: - resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} - engines: {node: '>=16'} + resolution: + { + integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==, + } + engines: { node: ">=16" } markdown-table@3.0.4: - resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + resolution: + { + integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==, + } math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, + } + engines: { node: ">= 0.4" } md5.js@1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + resolution: + { + integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==, + } md5@2.3.0: - resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + resolution: + { + integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==, + } mdast-util-find-and-replace@3.0.2: - resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} + resolution: + { + integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==, + } mdast-util-from-markdown@2.0.3: - resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} + resolution: + { + integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==, + } mdast-util-gfm-autolink-literal@2.0.1: - resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} + resolution: + { + integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==, + } mdast-util-gfm-footnote@2.1.0: - resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} + resolution: + { + integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==, + } mdast-util-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + resolution: + { + integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==, + } mdast-util-gfm-table@2.0.0: - resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + resolution: + { + integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==, + } mdast-util-gfm-task-list-item@2.0.0: - resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + resolution: + { + integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==, + } mdast-util-gfm@3.1.0: - resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} + resolution: + { + integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==, + } mdast-util-mdx-expression@2.0.1: - resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} + resolution: + { + integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==, + } mdast-util-mdx-jsx@3.2.0: - resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} + resolution: + { + integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==, + } mdast-util-mdx@3.0.0: - resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} + resolution: + { + integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==, + } mdast-util-mdxjs-esm@2.0.1: - resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + resolution: + { + integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==, + } mdast-util-phrasing@4.1.0: - resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + resolution: + { + integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==, + } mdast-util-to-hast@13.2.1: - resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + resolution: + { + integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==, + } mdast-util-to-markdown@2.1.2: - resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + resolution: + { + integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==, + } mdast-util-to-string@4.0.0: - resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + resolution: + { + integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==, + } media-typer@1.1.0: - resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==, + } + engines: { node: ">= 0.8" } merge-descriptors@2.0.0: - resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==, + } + engines: { node: ">=18" } merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + resolution: + { + integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, + } merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, + } + engines: { node: ">= 8" } micro-ftch@0.3.1: - resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} + resolution: + { + integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==, + } micromark-core-commonmark@2.0.3: - resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + resolution: + { + integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==, + } micromark-extension-gfm-autolink-literal@2.1.0: - resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + resolution: + { + integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==, + } micromark-extension-gfm-footnote@2.1.0: - resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + resolution: + { + integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==, + } micromark-extension-gfm-strikethrough@2.1.0: - resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + resolution: + { + integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==, + } micromark-extension-gfm-table@2.1.1: - resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + resolution: + { + integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==, + } micromark-extension-gfm-tagfilter@2.0.0: - resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + resolution: + { + integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==, + } micromark-extension-gfm-task-list-item@2.1.0: - resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + resolution: + { + integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==, + } micromark-extension-gfm@3.0.0: - resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + resolution: + { + integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==, + } micromark-extension-mdx-expression@3.0.1: - resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==} + resolution: + { + integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==, + } micromark-extension-mdx-jsx@3.0.2: - resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==} + resolution: + { + integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==, + } micromark-extension-mdx-md@2.0.0: - resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + resolution: + { + integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==, + } micromark-extension-mdxjs-esm@3.0.0: - resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} + resolution: + { + integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==, + } micromark-extension-mdxjs@3.0.0: - resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} + resolution: + { + integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==, + } micromark-factory-destination@2.0.1: - resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + resolution: + { + integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==, + } micromark-factory-label@2.0.1: - resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + resolution: + { + integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==, + } micromark-factory-mdx-expression@2.0.3: - resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==} + resolution: + { + integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==, + } micromark-factory-space@2.0.1: - resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + resolution: + { + integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==, + } micromark-factory-title@2.0.1: - resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + resolution: + { + integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==, + } micromark-factory-whitespace@2.0.1: - resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + resolution: + { + integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==, + } micromark-util-character@2.1.1: - resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + resolution: + { + integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==, + } micromark-util-chunked@2.0.1: - resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + resolution: + { + integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==, + } micromark-util-classify-character@2.0.1: - resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + resolution: + { + integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==, + } micromark-util-combine-extensions@2.0.1: - resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + resolution: + { + integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==, + } micromark-util-decode-numeric-character-reference@2.0.2: - resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + resolution: + { + integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==, + } micromark-util-decode-string@2.0.1: - resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + resolution: + { + integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==, + } micromark-util-encode@2.0.1: - resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + resolution: + { + integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==, + } micromark-util-events-to-acorn@2.0.3: - resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==} + resolution: + { + integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==, + } micromark-util-html-tag-name@2.0.1: - resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + resolution: + { + integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==, + } micromark-util-normalize-identifier@2.0.1: - resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + resolution: + { + integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==, + } micromark-util-resolve-all@2.0.1: - resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + resolution: + { + integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==, + } micromark-util-sanitize-uri@2.0.1: - resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + resolution: + { + integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==, + } micromark-util-subtokenize@2.1.0: - resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + resolution: + { + integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==, + } micromark-util-symbol@2.0.1: - resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + resolution: + { + integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==, + } micromark-util-types@2.0.2: - resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + resolution: + { + integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==, + } micromark@4.0.2: - resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + resolution: + { + integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==, + } micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} + resolution: + { + integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==, + } + engines: { node: ">=8.6" } miller-rabin@4.0.1: - resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + resolution: + { + integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==, + } hasBin: true mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, + } + engines: { node: ">= 0.6" } mime-db@1.54.0: - resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==, + } + engines: { node: ">= 0.6" } mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, + } + engines: { node: ">= 0.6" } mime-types@3.0.2: - resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==, + } + engines: { node: ">=18" } mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==, + } + engines: { node: ">=6" } mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==, + } + engines: { node: ">=12" } minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + resolution: + { + integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==, + } minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + resolution: + { + integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==, + } minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} - engines: {node: 18 || 20 || >=22} + resolution: + { + integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==, + } + engines: { node: 18 || 20 || >=22 } minimatch@3.1.5: - resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + resolution: + { + integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==, + } minimatch@7.4.9: - resolution: {integrity: sha512-Brg/fp/iAVDOQoHxkuN5bEYhyQlZhxddI78yWsCbeEwTHXQjlNLtiJDUsp1GIptVqMI7/gkJMz4vVAc01mpoBw==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-Brg/fp/iAVDOQoHxkuN5bEYhyQlZhxddI78yWsCbeEwTHXQjlNLtiJDUsp1GIptVqMI7/gkJMz4vVAc01mpoBw==, + } + engines: { node: ">=10" } minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + resolution: + { + integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, + } mipd@0.0.7: - resolution: {integrity: sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==} + resolution: + { + integrity: sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true mkdirp@2.1.6: - resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==, + } + engines: { node: ">=10" } hasBin: true + mri@1.2.0: + resolution: + { + integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==, + } + engines: { node: ">=4" } + ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + resolution: + { + integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==, + } ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, + } msw@2.14.6: - resolution: {integrity: sha512-ALe+N10S72cyx94cMcy3Zs4HhXCj35sgeAL4c+WTvKi0zWnbd8/h0lcFqv0mb2P+aSgAdD7p9HzvA0DiUPxsyg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-ALe+N10S72cyx94cMcy3Zs4HhXCj35sgeAL4c+WTvKi0zWnbd8/h0lcFqv0mb2P+aSgAdD7p9HzvA0DiUPxsyg==, + } + engines: { node: ">=18" } hasBin: true peerDependencies: - typescript: '>= 4.8.x' + typescript: ">= 4.8.x" peerDependenciesMeta: typescript: optional: true multiformats@9.9.0: - resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} + resolution: + { + integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==, + } mute-stream@3.0.0: - resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} - engines: {node: ^20.17.0 || >=22.9.0} + resolution: + { + integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==, + } + engines: { node: ^20.17.0 || >=22.9.0 } nanoid@3.3.15: - resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + resolution: + { + integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==, + } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } hasBin: true napi-postinstall@0.3.4: - resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + resolution: + { + integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==, + } + engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } hasBin: true natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + resolution: + { + integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, + } negotiator@1.0.0: - resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==, + } + engines: { node: ">= 0.6" } next-themes@0.4.6: - resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} + resolution: + { + integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==, + } peerDependencies: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc next@16.2.3: - resolution: {integrity: sha512-9V3zV4oZFza3PVev5/poB9g0dEafVcgNyQ8eTRop8GvxZjV2G15FC5ARuG1eFD42QgeYkzJBJzHghNP8Ad9xtA==} - engines: {node: '>=20.9.0'} + resolution: + { + integrity: sha512-9V3zV4oZFza3PVev5/poB9g0dEafVcgNyQ8eTRop8GvxZjV2G15FC5ARuG1eFD42QgeYkzJBJzHghNP8Ad9xtA==, + } + engines: { node: ">=20.9.0" } hasBin: true peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.51.1 - babel-plugin-react-compiler: '*' + "@opentelemetry/api": ^1.1.0 + "@playwright/test": ^1.51.1 + babel-plugin-react-compiler: "*" react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 sass: ^1.3.0 peerDependenciesMeta: - '@opentelemetry/api': + "@opentelemetry/api": optional: true - '@playwright/test': + "@playwright/test": optional: true babel-plugin-react-compiler: optional: true @@ -5246,23 +8744,44 @@ packages: optional: true node-addon-api@2.0.2: - resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} + resolution: + { + integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==, + } + + node-addon-api@7.1.1: + resolution: + { + integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==, + } node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} + resolution: + { + integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==, + } + engines: { node: ">=10.5.0" } deprecated: Use your platform's native DOMException instead node-exports-info@1.6.2: - resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==, + } + engines: { node: ">= 0.4" } node-fetch-native@1.6.7: - resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + 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} + resolution: + { + integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==, + } + engines: { node: 4.x || >=6.0.0 } peerDependencies: encoding: ^0.1.0 peerDependenciesMeta: @@ -5270,311 +8789,530 @@ packages: optional: true node-fetch@3.3.2: - resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } node-gyp-build@4.8.4: - resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + resolution: + { + integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==, + } hasBin: true node-mock-http@1.0.4: - resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} + resolution: + { + integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==, + } node-releases@2.0.50: - resolution: {integrity: sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==, + } + engines: { node: ">=18" } normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, + } + engines: { node: ">=0.10.0" } npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } obj-multiplex@1.0.0: - resolution: {integrity: sha512-0GNJAOsHoBHeNTvl5Vt6IWnpUEcc3uSRxzBri7EDyIcMgYvnY2JL2qdeV5zTMjWQX5OHcD5amcW2HFfDh0gjIA==} + resolution: + { + integrity: sha512-0GNJAOsHoBHeNTvl5Vt6IWnpUEcc3uSRxzBri7EDyIcMgYvnY2JL2qdeV5zTMjWQX5OHcD5amcW2HFfDh0gjIA==, + } object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, + } + engines: { node: ">=0.10.0" } object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, + } + engines: { node: ">= 0.4" } object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==, + } + engines: { node: ">= 0.4" } object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==, + } + engines: { node: ">= 0.4" } object.entries@1.1.9: - resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==, + } + engines: { node: ">= 0.4" } object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==, + } + engines: { node: ">= 0.4" } object.groupby@1.0.3: - resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==, + } + engines: { node: ">= 0.4" } object.values@1.2.1: - resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==, + } + engines: { node: ">= 0.4" } ofetch@1.5.1: - resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + resolution: + { + integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==, + } on-exit-leak-free@0.2.0: - resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==} + resolution: + { + integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==, + } on-exit-leak-free@2.1.2: - resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==, + } + engines: { node: ">=14.0.0" } on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==, + } + engines: { node: ">= 0.8" } once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + resolution: + { + integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, + } onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==, + } + engines: { node: ">=6" } onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==, + } + engines: { node: ">=12" } oniguruma-parser@0.12.2: - resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==} + resolution: + { + integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==, + } oniguruma-to-es@2.3.0: - resolution: {integrity: sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==} + resolution: + { + integrity: sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==, + } oniguruma-to-es@4.3.6: - resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} + resolution: + { + integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==, + } openapi-fetch@0.13.8: - resolution: {integrity: sha512-yJ4QKRyNxE44baQ9mY5+r/kAzZ8yXMemtNAOFwOzRXJscdjSxxzWSNlyBAr+o5JjkUw9Lc3W7OIoca0cY3PYnQ==} + resolution: + { + integrity: sha512-yJ4QKRyNxE44baQ9mY5+r/kAzZ8yXMemtNAOFwOzRXJscdjSxxzWSNlyBAr+o5JjkUw9Lc3W7OIoca0cY3PYnQ==, + } openapi-typescript-helpers@0.0.15: - resolution: {integrity: sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==} + resolution: + { + integrity: sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==, + } optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} + resolution: + { + integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==, + } + engines: { node: ">= 0.8.0" } ora@6.3.1: - resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } outvariant@1.4.3: - resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + resolution: + { + integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==, + } own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==, + } + engines: { node: ">= 0.4" } ox@0.14.29: - resolution: {integrity: sha512-M5j87Ec4V99MQdRct/g09eWXW60g6zhHTUs1lr4deUtrPDnezBdCJTgKd7pxqTpSZBFveV0ALi9jMMuT1qKyNg==} + resolution: + { + integrity: sha512-M5j87Ec4V99MQdRct/g09eWXW60g6zhHTUs1lr4deUtrPDnezBdCJTgKd7pxqTpSZBFveV0ALi9jMMuT1qKyNg==, + } peerDependencies: - typescript: '>=5.4.0' + typescript: ">=5.4.0" peerDependenciesMeta: typescript: optional: true ox@0.6.7: - resolution: {integrity: sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==} + resolution: + { + integrity: sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==, + } peerDependencies: - typescript: '>=5.4.0' + typescript: ">=5.4.0" peerDependenciesMeta: typescript: optional: true ox@0.6.9: - resolution: {integrity: sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==} + resolution: + { + integrity: sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==, + } peerDependencies: - typescript: '>=5.4.0' + typescript: ">=5.4.0" peerDependenciesMeta: typescript: optional: true ox@0.9.17: - resolution: {integrity: sha512-rKAnhzhRU3Xh3hiko+i1ZxywZ55eWQzeS/Q4HRKLx2PqfHOolisZHErSsJVipGlmQKHW5qwOED/GighEw9dbLg==} + resolution: + { + integrity: sha512-rKAnhzhRU3Xh3hiko+i1ZxywZ55eWQzeS/Q4HRKLx2PqfHOolisZHErSsJVipGlmQKHW5qwOED/GighEw9dbLg==, + } peerDependencies: - typescript: '>=5.4.0' + typescript: ">=5.4.0" peerDependenciesMeta: typescript: optional: true ox@0.9.6: - resolution: {integrity: sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==} + resolution: + { + integrity: sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==, + } peerDependencies: - typescript: '>=5.4.0' + typescript: ">=5.4.0" peerDependenciesMeta: typescript: optional: true ox@https://pkg.pr.new/ox@386a3439fe1ce76d237930f8c6e6bb493746069a: - resolution: {tarball: https://pkg.pr.new/ox@386a3439fe1ce76d237930f8c6e6bb493746069a} + resolution: + { + tarball: https://pkg.pr.new/ox@386a3439fe1ce76d237930f8c6e6bb493746069a, + } version: 0.14.26-386a343.0 peerDependencies: - typescript: '>=5.4.0' + typescript: ">=5.4.0" peerDependenciesMeta: typescript: optional: true p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==, + } + engines: { node: ">=6" } p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, + } + engines: { node: ">=10" } p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==, + } + engines: { node: ">=8" } p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, + } + engines: { node: ">=10" } p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==, + } + engines: { node: ">=6" } parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, + } + engines: { node: ">=6" } parse-asn1@5.1.9: - resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==, + } + engines: { node: ">= 0.10" } parse-entities@4.0.2: - resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + resolution: + { + integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==, + } parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, + } + engines: { node: ">=8" } parse-numeric-range@1.3.0: - resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==} + resolution: + { + integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==, + } parse5@7.3.0: - resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + resolution: + { + integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==, + } parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==, + } + engines: { node: ">= 0.8" } path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + resolution: + { + integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==, + } path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, + } + engines: { node: ">=8" } path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, + } + engines: { node: ">=8" } path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==, + } + engines: { node: ">=12" } path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + resolution: + { + integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, + } path-to-regexp@6.3.0: - resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + resolution: + { + integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==, + } path-to-regexp@8.4.2: - resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + resolution: + { + integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==, + } path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, + } + engines: { node: ">=8" } pbkdf2@3.1.6: - resolution: {integrity: sha512-BT6eelPB1EyGHo8pC0o9Bl6k6SYVhKO1jEbd3lcTrtr7XHdjP8BW1YpfCV3G9Kwkxgattk+S5q2/RvuttCsS1g==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-BT6eelPB1EyGHo8pC0o9Bl6k6SYVhKO1jEbd3lcTrtr7XHdjP8BW1YpfCV3G9Kwkxgattk+S5q2/RvuttCsS1g==, + } + engines: { node: ">= 0.10" } picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + resolution: + { + integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, + } picomatch@2.3.2: - resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} - engines: {node: '>=8.6'} + resolution: + { + integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==, + } + engines: { node: ">=8.6" } picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==, + } + engines: { node: ">=12" } pify@3.0.0: - resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==, + } + engines: { node: ">=4" } pify@5.0.0: - resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==, + } + engines: { node: ">=10" } pino-abstract-transport@0.5.0: - resolution: {integrity: sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==} + resolution: + { + integrity: sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==, + } pino-abstract-transport@3.0.0: - resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} + resolution: + { + integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==, + } pino-pretty@13.1.3: - resolution: {integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==} + resolution: + { + integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==, + } hasBin: true pino-std-serializers@4.0.0: - resolution: {integrity: sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==} + resolution: + { + integrity: sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==, + } pino@7.11.0: - resolution: {integrity: sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==} + resolution: + { + integrity: sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==, + } hasBin: true pkce-challenge@5.0.1: - resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} - engines: {node: '>=16.20.0'} + resolution: + { + integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==, + } + engines: { node: ">=16.20.0" } pngjs@5.0.0: - resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} - engines: {node: '>=10.13.0'} + resolution: + { + integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==, + } + engines: { node: ">=10.13.0" } pony-cause@2.1.11: - resolution: {integrity: sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==} - engines: {node: '>=12.0.0'} + resolution: + { + integrity: sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==, + } + engines: { node: ">=12.0.0" } popmotion@11.0.3: - resolution: {integrity: sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==} + resolution: + { + integrity: sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==, + } porto@0.2.35: - resolution: {integrity: sha512-gu9FfjjvvYBgQXUHWTp6n3wkTxVtEcqFotM7i3GEZeoQbvLGbssAicCz6hFZ8+xggrJWwi/RLmbwNra50SMmUQ==} + resolution: + { + integrity: sha512-gu9FfjjvvYBgQXUHWTp6n3wkTxVtEcqFotM7i3GEZeoQbvLGbssAicCz6hFZ8+xggrJWwi/RLmbwNra50SMmUQ==, + } hasBin: true peerDependencies: - '@tanstack/react-query': '>=5.59.0' - '@wagmi/core': '>=2.16.3' - expo-auth-session: '>=7.0.8' - expo-crypto: '>=15.0.7' - expo-web-browser: '>=15.0.8' - react: '>=18' - react-native: '>=0.81.4' - typescript: '>=5.4.0' - viem: '>=2.37.0' - wagmi: '>=2.0.0' + "@tanstack/react-query": ">=5.59.0" + "@wagmi/core": ">=2.16.3" + expo-auth-session: ">=7.0.8" + expo-crypto: ">=15.0.7" + expo-web-browser: ">=15.0.8" + react: ">=18" + react-native: ">=0.81.4" + typescript: ">=5.4.0" + viem: ">=2.37.0" + wagmi: ">=2.0.0" peerDependenciesMeta: - '@tanstack/react-query': + "@tanstack/react-query": optional: true expo-auth-session: optional: true @@ -5592,895 +9330,1575 @@ packages: optional: true poseidon-lite@0.2.1: - resolution: {integrity: sha512-xIr+G6HeYfOhCuswdqcFpSX47SPhm0EpisWJ6h7fHlWwaVIvH3dLnejpatrtw6Xc6HaLrpq05y7VRfvDmDGIog==} + resolution: + { + integrity: sha512-xIr+G6HeYfOhCuswdqcFpSX47SPhm0EpisWJ6h7fHlWwaVIvH3dLnejpatrtw6Xc6HaLrpq05y7VRfvDmDGIog==, + } possible-typed-array-names@1.1.0: - resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==, + } + engines: { node: ">= 0.4" } postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + resolution: + { + integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==, + } postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} + resolution: + { + integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==, + } + engines: { node: ^10 || ^12 || >=14 } postcss@8.5.16: - resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==} - engines: {node: ^10 || ^12 || >=14} + resolution: + { + integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==, + } + engines: { node: ^10 || ^12 || >=14 } posthog-js@1.379.3: - resolution: {integrity: sha512-Ej0Z6ZdaG8c0NoHtY0k1xiV/ws2WooX44Yr1GcuPU82uee+r6EuWf6fBsp9EDc5F/6MHe0RRpZG0YbLqM3TLTg==} + resolution: + { + integrity: sha512-Ej0Z6ZdaG8c0NoHtY0k1xiV/ws2WooX44Yr1GcuPU82uee+r6EuWf6fBsp9EDc5F/6MHe0RRpZG0YbLqM3TLTg==, + } preact@10.24.2: - resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} + resolution: + { + integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==, + } preact@10.29.3: - resolution: {integrity: sha512-D9NL1GAnJZhc3RndVs4gDdxEeU9TcHgywMrhhOsnpdlvFjdbx0gAsLUnH6JEhlJH5giL7Tx5biWPUSEXE/HPzw==} + resolution: + { + integrity: sha512-D9NL1GAnJZhc3RndVs4gDdxEeU9TcHgywMrhhOsnpdlvFjdbx0gAsLUnH6JEhlJH5giL7Tx5biWPUSEXE/HPzw==, + } prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} + resolution: + { + integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, + } + engines: { node: ">= 0.8.0" } process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + resolution: + { + integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==, + } process-warning@1.0.0: - resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==} + resolution: + { + integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==, + } prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==, + } + engines: { node: ">= 6" } prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + resolution: + { + integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, + } property-information@7.2.0: - resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==} + resolution: + { + integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==, + } proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, + } + engines: { node: ">= 0.10" } proxy-compare@2.6.0: - resolution: {integrity: sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw==} + resolution: + { + integrity: sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw==, + } proxy-from-env@2.1.0: - resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==, + } + engines: { node: ">=10" } public-encrypt@4.0.3: - resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + resolution: + { + integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==, + } pump@3.0.4: - resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + resolution: + { + integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==, + } punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, + } + engines: { node: ">=6" } qrcode@1.5.3: - resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} - engines: {node: '>=10.13.0'} + resolution: + { + integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==, + } + engines: { node: ">=10.13.0" } hasBin: true qrcode@1.5.4: - resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} - engines: {node: '>=10.13.0'} + resolution: + { + integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==, + } + engines: { node: ">=10.13.0" } hasBin: true qs@6.15.3: - resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} - engines: {node: '>=0.6'} + resolution: + { + integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==, + } + engines: { node: ">=0.6" } query-selector-shadow-dom@1.0.1: - resolution: {integrity: sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==} + resolution: + { + integrity: sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==, + } query-string@7.1.3: - resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==, + } + engines: { node: ">=6" } queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + resolution: + { + integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, + } quick-format-unescaped@4.0.4: - resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + resolution: + { + integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==, + } radix3@1.1.2: - resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + resolution: + { + integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==, + } randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + resolution: + { + integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==, + } randomfill@1.0.4: - resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + resolution: + { + integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==, + } range-parser@1.3.0: - resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==, + } + engines: { node: ">= 0.6" } raw-body@3.0.2: - resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==, + } + engines: { node: ">= 0.10" } react-dom@19.2.2: - resolution: {integrity: sha512-fhyD2BLrew6qYf4NNtHff1rLXvzR25rq49p+FeqByOazc6TcSi2n8EYulo5C1PbH+1uBW++5S1SG7FcUU6mlDg==} + resolution: + { + integrity: sha512-fhyD2BLrew6qYf4NNtHff1rLXvzR25rq49p+FeqByOazc6TcSi2n8EYulo5C1PbH+1uBW++5S1SG7FcUU6mlDg==, + } peerDependencies: react: ^19.2.2 react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + resolution: + { + integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==, + } + + react-is@19.2.8: + resolution: + { + integrity: sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==, + } react-remove-scroll-bar@2.3.8: - resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==, + } + engines: { node: ">=10" } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: - '@types/react': + "@types/react": optional: true react-remove-scroll@2.7.2: - resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==, + } + engines: { node: ">=10" } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true react-style-singleton@2.2.3: - resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==, + } + engines: { node: ">=10" } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true + react-test-renderer@19.2.2: + resolution: + { + integrity: sha512-nUHqzl8hoNow/baW+UflctPcr/ClPpOnKGfsnDr/i7Ng+FaYxMryRhAAbIP1fg0Q9BxC15E9+8ikGLT55Wzh7Q==, + } + peerDependencies: + react: ^19.2.2 + react-transition-state@1.1.5: - resolution: {integrity: sha512-ITY2mZqc2dWG2eitJkYNdcSFW8aKeOlkL2A/vowRrLL8GH3J6Re/SpD/BLvQzrVOTqjsP0b5S9N10vgNNzwMUQ==} + resolution: + { + integrity: sha512-ITY2mZqc2dWG2eitJkYNdcSFW8aKeOlkL2A/vowRrLL8GH3J6Re/SpD/BLvQzrVOTqjsP0b5S9N10vgNNzwMUQ==, + } peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' + react: ">=16.8.0" + react-dom: ">=16.8.0" react-use-measure@2.1.7: - resolution: {integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==} + resolution: + { + integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==, + } peerDependencies: - react: '>=16.13' - react-dom: '>=16.13' + react: ">=16.13" + react-dom: ">=16.13" peerDependenciesMeta: react-dom: optional: true react@19.2.2: - resolution: {integrity: sha512-BdOGOY8OKRBcgoDkwqA8Q5XvOIhoNx/Sh6BnGJlet2Abt0X5BK0BDrqGyQgLhAVjD2nAg5f6o01u/OPUhG022Q==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-BdOGOY8OKRBcgoDkwqA8Q5XvOIhoNx/Sh6BnGJlet2Abt0X5BK0BDrqGyQgLhAVjD2nAg5f6o01u/OPUhG022Q==, + } + engines: { node: ">=0.10.0" } readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + resolution: + { + integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==, + } readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==, + } + engines: { node: ">= 6" } readdirp@4.1.2: - resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} - engines: {node: '>= 14.18.0'} + resolution: + { + integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==, + } + engines: { node: ">= 14.18.0" } readdirp@5.0.0: - resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} - engines: {node: '>= 20.19.0'} + resolution: + { + integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==, + } + engines: { node: ">= 20.19.0" } real-require@0.1.0: - resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==} - engines: {node: '>= 12.13.0'} + resolution: + { + integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==, + } + engines: { node: ">= 12.13.0" } recast@0.23.12: - resolution: {integrity: sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==, + } + engines: { node: ">= 4" } recma-build-jsx@1.0.0: - resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} + resolution: + { + integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==, + } recma-jsx@1.0.1: - resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==} + resolution: + { + integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==, + } peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 recma-parse@1.0.0: - resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} + resolution: + { + integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==, + } recma-stringify@1.0.0: - resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + resolution: + { + integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==, + } reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==, + } + engines: { node: ">= 0.4" } regex-recursion@5.1.1: - resolution: {integrity: sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==} + resolution: + { + integrity: sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==, + } regex-recursion@6.0.2: - resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + resolution: + { + integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==, + } regex-utilities@2.3.0: - resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + resolution: + { + integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==, + } regex@5.1.1: - resolution: {integrity: sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==} + resolution: + { + integrity: sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==, + } regex@6.1.0: - resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + resolution: + { + integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==, + } regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==, + } + engines: { node: ">= 0.4" } rehype-parse@9.0.1: - resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==} + resolution: + { + integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==, + } rehype-pretty-code@0.14.3: - resolution: {integrity: sha512-Cz692FeYusTjT5cfFWLc4r7JhgC3/JlJptgUh4iffBxWxUnWW1oqbWFi7jGCeq00DYUm8yzoTnvpocaYa5x82g==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-Cz692FeYusTjT5cfFWLc4r7JhgC3/JlJptgUh4iffBxWxUnWW1oqbWFi7jGCeq00DYUm8yzoTnvpocaYa5x82g==, + } + engines: { node: ">=18" } peerDependencies: shiki: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 rehype-recma@1.0.0: - resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==} + resolution: + { + integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==, + } remark-gfm@4.0.1: - resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} + resolution: + { + integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==, + } remark-mdx@3.1.1: - resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==} + resolution: + { + integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==, + } remark-parse@11.0.0: - resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + resolution: + { + integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==, + } remark-rehype@11.1.2: - resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} + resolution: + { + integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==, + } remark-stringify@11.0.0: - resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + resolution: + { + integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==, + } remark@15.0.1: - resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==} + resolution: + { + integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==, + } require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, + } + engines: { node: ">=0.10.0" } require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, + } + engines: { node: ">=0.10.0" } require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + resolution: + { + integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==, + } resize-observer-polyfill@1.5.1: - resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + resolution: + { + integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==, + } resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, + } + engines: { node: ">=4" } resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolution: + { + integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==, + } resolve@2.0.0-next.7: - resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==, + } + engines: { node: ">= 0.4" } hasBin: true restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } rettime@0.11.11: - resolution: {integrity: sha512-ILJRqVWBCTlg9r42fFgwVZx1gnFAcQF8mRoMkbgQfIrjEDf9nbBFDFx00oloOa+Q869FUtaYDXZvEfnecQSCoQ==} + resolution: + { + integrity: sha512-ILJRqVWBCTlg9r42fFgwVZx1gnFAcQF8mRoMkbgQfIrjEDf9nbBFDFx00oloOa+Q869FUtaYDXZvEfnecQSCoQ==, + } reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + resolution: + { + integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==, + } + engines: { iojs: ">=1.0.0", node: ">=0.10.0" } ripemd160@2.0.3: - resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==, + } + engines: { node: ">= 0.8" } router@2.2.0: - resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} - engines: {node: '>= 18'} + resolution: + { + integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==, + } + engines: { node: ">= 18" } rpc-websockets@9.3.9: - resolution: {integrity: sha512-2iQDaTB4g5fDB2ihrTFSJSibCEuxaRi1q7qTW7ZO9/M5/TC+ToHA4D9/ffNLEbAoHNNrcdeP05oATNk44SKZXA==} + resolution: + { + integrity: sha512-2iQDaTB4g5fDB2ihrTFSJSibCEuxaRi1q7qTW7ZO9/M5/TC+ToHA4D9/ffNLEbAoHNNrcdeP05oATNk44SKZXA==, + } run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + resolution: + { + integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, + } safe-array-concat@1.1.4: - resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} - engines: {node: '>=0.4'} + resolution: + { + integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==, + } + engines: { node: ">=0.4" } safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + resolution: + { + integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, + } safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + resolution: + { + integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, + } safe-push-apply@1.0.0: - resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==, + } + engines: { node: ">= 0.4" } safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==, + } + engines: { node: ">= 0.4" } safe-stable-stringify@2.5.0: - resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==, + } + engines: { node: ">=10" } safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + resolution: + { + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, + } scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + resolution: + { + integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==, + } scroll-into-view-if-needed@3.1.0: - resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} + resolution: + { + integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==, + } secure-json-parse@4.1.0: - resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} + resolution: + { + integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==, + } semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + resolution: + { + integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==, + } hasBin: true semver@7.8.5: - resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==, + } + engines: { node: ">=10" } hasBin: true send@1.2.1: - resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} - engines: {node: '>= 18'} + resolution: + { + integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==, + } + engines: { node: ">= 18" } serve-static@2.2.1: - resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} - engines: {node: '>= 18'} + resolution: + { + integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==, + } + engines: { node: ">= 18" } set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + resolution: + { + integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==, + } set-cookie-parser@3.1.1: - resolution: {integrity: sha512-vM9SUhjsUYs6UeJUmygc5Ofm5eQGe85riob5ju6XCgFGJI5PLV4nrDAQpQjd+LkFBpAkADn5BQQpZ9EUNkyLuA==} + resolution: + { + integrity: sha512-vM9SUhjsUYs6UeJUmygc5Ofm5eQGe85riob5ju6XCgFGJI5PLV4nrDAQpQjd+LkFBpAkADn5BQQpZ9EUNkyLuA==, + } set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==, + } + engines: { node: ">= 0.4" } set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==, + } + engines: { node: ">= 0.4" } set-proto@1.0.0: - resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==, + } + engines: { node: ">= 0.4" } setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + resolution: + { + integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==, + } sha.js@2.4.12: - resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==, + } + engines: { node: ">= 0.10" } hasBin: true shadcn@2.9.3-canary.0: - resolution: {integrity: sha512-2oOusRSdNZoy8zzj6TlwWMlL6IhVZTcfPkqYXNLPAANj92J42zJ5G2QqIep/rKbrfRwFO8QRDq7evVdmYsC+1w==} + resolution: + { + integrity: sha512-2oOusRSdNZoy8zzj6TlwWMlL6IhVZTcfPkqYXNLPAANj92J42zJ5G2QqIep/rKbrfRwFO8QRDq7evVdmYsC+1w==, + } hasBin: true shallowequal@1.1.0: - resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + resolution: + { + integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==, + } sharp@0.34.5: - resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + resolution: + { + integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==, + } + engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, + } + engines: { node: ">=8" } shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, + } + engines: { node: ">=8" } shiki@1.29.2: - resolution: {integrity: sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg==} + resolution: + { + integrity: sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg==, + } shiki@4.3.0: - resolution: {integrity: sha512-NKKjWzR6LIGL3sXBrWDw9sDS9cxx42/DkysaNqJEeOWE8Kix5gpak0bc00OfDVEO4oyXSyz8+aRaqKoBD1yo7A==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-NKKjWzR6LIGL3sXBrWDw9sDS9cxx42/DkysaNqJEeOWE8Kix5gpak0bc00OfDVEO4oyXSyz8+aRaqKoBD1yo7A==, + } + engines: { node: ">=20" } side-channel-list@1.0.1: - resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==, + } + engines: { node: ">= 0.4" } side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, + } + engines: { node: ">= 0.4" } side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, + } + engines: { node: ">= 0.4" } side-channel@1.1.1: - resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==, + } + engines: { node: ">= 0.4" } signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + resolution: + { + integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, + } signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} + resolution: + { + integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, + } + engines: { node: ">=14" } sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + resolution: + { + integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==, + } socket.io-client@4.8.3: - resolution: {integrity: sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==, + } + engines: { node: ">=10.0.0" } socket.io-parser@4.2.6: - resolution: {integrity: sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==, + } + engines: { node: ">=10.0.0" } sonic-boom@2.8.0: - resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==} + resolution: + { + integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==, + } sonic-boom@4.2.1: - resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + resolution: + { + integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==, + } sonner@2.0.7: - resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} + resolution: + { + integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==, + } peerDependencies: react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, + } + engines: { node: ">=0.10.0" } source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, + } + engines: { node: ">=0.10.0" } source-map@0.7.6: - resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} - engines: {node: '>= 12'} + resolution: + { + integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==, + } + engines: { node: ">= 12" } space-separated-tokens@2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + resolution: + { + integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==, + } split-on-first@1.1.0: - resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==, + } + engines: { node: ">=6" } split2@4.2.0: - resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} - engines: {node: '>= 10.x'} + resolution: + { + integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==, + } + engines: { node: ">= 10.x" } sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + resolution: + { + integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==, + } stable-hash@0.0.5: - resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + resolution: + { + integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==, + } statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==, + } + engines: { node: ">= 0.8" } stdin-discarder@0.1.0: - resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } stop-iteration-iterator@1.1.0: - resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==, + } + engines: { node: ">= 0.4" } stream-browserify@3.0.0: - resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + resolution: + { + integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==, + } stream-chain@2.2.5: - resolution: {integrity: sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==} + resolution: + { + integrity: sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==, + } stream-json@1.9.1: - resolution: {integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==} + resolution: + { + integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==, + } stream-shift@1.0.3: - resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + resolution: + { + integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==, + } strict-event-emitter@0.5.1: - resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + resolution: + { + integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==, + } strict-uri-encode@2.0.0: - resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==, + } + engines: { node: ">=4" } string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, + } + engines: { node: ">=8" } string.prototype.includes@2.0.1: - resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==, + } + engines: { node: ">= 0.4" } string.prototype.matchall@4.0.12: - resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==, + } + engines: { node: ">= 0.4" } string.prototype.repeat@1.0.0: - resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + resolution: + { + integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==, + } string.prototype.trim@1.2.11: - resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==, + } + engines: { node: ">= 0.4" } string.prototype.trimend@1.0.10: - resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==, + } + engines: { node: ">= 0.4" } string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==, + } + engines: { node: ">= 0.4" } string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + resolution: + { + integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==, + } string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + resolution: + { + integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, + } stringify-entities@4.0.4: - resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + resolution: + { + integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==, + } stringify-object@5.0.0: - resolution: {integrity: sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==, + } + engines: { node: ">=14.16" } strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, + } + engines: { node: ">=8" } strip-ansi@7.2.0: - resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==, + } + engines: { node: ">=12" } strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, + } + engines: { node: ">=4" } strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==, + } + engines: { node: ">=12" } strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, + } + engines: { node: ">=8" } strip-json-comments@5.0.3: - resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==, + } + engines: { node: ">=14.16" } style-to-js@1.1.21: - resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} + resolution: + { + integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==, + } style-to-object@1.0.14: - resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} + resolution: + { + integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==, + } style-value-types@5.0.0: - resolution: {integrity: sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==} + resolution: + { + integrity: sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==, + } styled-components@5.3.11: - resolution: {integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==, + } + engines: { node: ">=10" } peerDependencies: - react: '>= 16.8.0' - react-dom: '>= 16.8.0' - react-is: '>= 16.8.0' + react: ">= 16.8.0" + react-dom: ">= 16.8.0" + react-is: ">= 16.8.0" styled-jsx@5.1.6: - resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} - engines: {node: '>= 12.0.0'} + resolution: + { + integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==, + } + engines: { node: ">= 12.0.0" } peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + "@babel/core": "*" + babel-plugin-macros: "*" + react: ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" peerDependenciesMeta: - '@babel/core': + "@babel/core": optional: true babel-plugin-macros: optional: true superstruct@1.0.4: - resolution: {integrity: sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==, + } + engines: { node: ">=14.0.0" } superstruct@2.0.2: - resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} - engines: {node: '>=14.0.0'} + resolution: + { + integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==, + } + engines: { node: ">=14.0.0" } supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, + } + engines: { node: ">=4" } supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, + } + engines: { node: ">=8" } supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, + } + engines: { node: ">= 0.4" } tagged-tag@1.0.0: - resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==, + } + engines: { node: ">=20" } tailwind-merge@3.6.0: - resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} + resolution: + { + integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==, + } tailwindcss@4.3.2: - resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} + resolution: + { + integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==, + } + + tailwindcss@4.3.3: + resolution: + { + integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==, + } tapable@2.3.3: - resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==, + } + engines: { node: ">=6" } text-encoding-utf-8@1.0.2: - resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} + resolution: + { + integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==, + } thread-stream@0.15.2: - resolution: {integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==} + resolution: + { + integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==, + } tiny-invariant@1.3.3: - resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + resolution: + { + integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==, + } tinyexec@1.2.4: - resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==, + } + engines: { node: ">=18" } tinyglobby@0.2.17: - resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} - engines: {node: '>=12.0.0'} + resolution: + { + integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==, + } + engines: { node: ">=12.0.0" } tldts-core@7.4.5: - resolution: {integrity: sha512-pGrwzZDvPwKe+7NNUqAunb6rqTfynr0VOUhCMdqbu5xlvNiszsAJygRzwvpVycdzejlbpY+SWJOn+s75Og7FEA==} + resolution: + { + integrity: sha512-pGrwzZDvPwKe+7NNUqAunb6rqTfynr0VOUhCMdqbu5xlvNiszsAJygRzwvpVycdzejlbpY+SWJOn+s75Og7FEA==, + } tldts@7.4.5: - resolution: {integrity: sha512-RfEzKWcq5fHUOFq7J3rl3Oz6ylKGtcHqUznzj4EcXsxLSIjJcvpbXAQtWGeJQ0xKnimR5e0Cn+cn9TssfMzm+g==} + resolution: + { + integrity: sha512-RfEzKWcq5fHUOFq7J3rl3Oz6ylKGtcHqUznzj4EcXsxLSIjJcvpbXAQtWGeJQ0xKnimR5e0Cn+cn9TssfMzm+g==, + } hasBin: true to-buffer@1.2.2: - resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==, + } + engines: { node: ">= 0.4" } to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + resolution: + { + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, + } + engines: { node: ">=8.0" } toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} + resolution: + { + integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==, + } + engines: { node: ">=0.6" } tough-cookie@6.0.1: - resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} - engines: {node: '>=16'} + resolution: + { + integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==, + } + engines: { node: ">=16" } tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + resolution: + { + integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, + } trim-lines@3.0.1: - resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + resolution: + { + integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==, + } trough@2.2.0: - resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + resolution: + { + integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==, + } ts-api-utils@2.5.0: - resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} - engines: {node: '>=18.12'} + resolution: + { + integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==, + } + engines: { node: ">=18.12" } peerDependencies: - typescript: '>=4.8.4' + typescript: ">=4.8.4" ts-morph@18.0.0: - resolution: {integrity: sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA==} + resolution: + { + integrity: sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA==, + } ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + resolution: + { + integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==, + } hasBin: true peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" peerDependenciesMeta: - '@swc/core': + "@swc/core": optional: true - '@swc/wasm': + "@swc/wasm": optional: true tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + resolution: + { + integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==, + } tsconfig-paths@4.2.0: - resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==, + } + engines: { node: ">=6" } tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + resolution: + { + integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==, + } tslib@2.7.0: - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + resolution: + { + integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==, + } tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + resolution: + { + integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, + } tsx@4.22.5: - resolution: {integrity: sha512-F7JnSfPl5ASt6LqwWyUQ3T8BwN3q0eQEbFMYa2iRWaVQmmudo0d7fRmwM4O002gsvW1bs0yBYioutsAjqLJMvQ==} - engines: {node: '>=18.0.0'} + resolution: + { + integrity: sha512-F7JnSfPl5ASt6LqwWyUQ3T8BwN3q0eQEbFMYa2iRWaVQmmudo0d7fRmwM4O002gsvW1bs0yBYioutsAjqLJMvQ==, + } + engines: { node: ">=18.0.0" } hasBin: true tw-animate-css@1.4.0: - resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} + resolution: + { + integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==, + } type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + resolution: + { + integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, + } + engines: { node: ">= 0.8.0" } type-fest@5.7.0: - resolution: {integrity: sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==} - engines: {node: '>=20'} + resolution: + { + integrity: sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==, + } + engines: { node: ">=20" } type-is@2.1.0: - resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} - engines: {node: '>= 18'} + resolution: + { + integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==, + } + engines: { node: ">= 18" } typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==, + } + engines: { node: ">= 0.4" } typed-array-byte-length@1.0.3: - resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==, + } + engines: { node: ">= 0.4" } typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==, + } + engines: { node: ">= 0.4" } typed-array-length@1.0.8: - resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==, + } + engines: { node: ">= 0.4" } typescript-eslint@8.62.1: - resolution: {integrity: sha512-vymnnM5g0AKQDSAyfP12nMIBvgwgA42syg74kkuZ4x1VuTzwQKwc5h9rGxeShCjny5o+zWAb6OEoz7XLgrIkIw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + resolution: + { + integrity: sha512-vymnnM5g0AKQDSAyfP12nMIBvgwgA42syg74kkuZ4x1VuTzwQKwc5h9rGxeShCjny5o+zWAb6OEoz7XLgrIkIw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' + typescript: ">=4.8.4 <6.1.0" typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} + resolution: + { + integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, + } + engines: { node: ">=14.17" } hasBin: true ufo@1.6.4: - resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + resolution: + { + integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==, + } uint8arrays@3.1.0: - resolution: {integrity: sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog==} + resolution: + { + integrity: sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog==, + } unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==, + } + engines: { node: ">= 0.4" } uncrypto@0.1.3: - resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + resolution: + { + integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==, + } undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + resolution: + { + integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==, + } undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + resolution: + { + integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==, + } undici-types@7.28.0: - resolution: {integrity: sha512-LJAfY+2w6HGeT8d8J1wNQsUGUEGio6NWWpwdwurQe4f6oojzCFuGLizl1KSve4irsTxyLly1QhEeE6iapdaIvQ==} + resolution: + { + integrity: sha512-LJAfY+2w6HGeT8d8J1wNQsUGUEGio6NWWpwdwurQe4f6oojzCFuGLizl1KSve4irsTxyLly1QhEeE6iapdaIvQ==, + } unified@11.0.5: - resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + resolution: + { + integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==, + } unist-util-is@6.0.1: - resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + resolution: + { + integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==, + } unist-util-position-from-estree@2.0.0: - resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + resolution: + { + integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==, + } unist-util-position@5.0.0: - resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + resolution: + { + integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==, + } unist-util-remove-position@5.0.0: - resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + resolution: + { + integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==, + } unist-util-stringify-position@4.0.0: - resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + resolution: + { + integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==, + } unist-util-visit-parents@6.0.2: - resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + resolution: + { + integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==, + } unist-util-visit@5.1.0: - resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + resolution: + { + integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==, + } universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} + resolution: + { + integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, + } + engines: { node: ">= 10.0.0" } unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, + } + engines: { node: ">= 0.8" } unrs-resolver@1.12.2: - resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==} + resolution: + { + integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==, + } unstorage@1.17.5: - resolution: {integrity: sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==} + 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 + "@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' + db0: ">=0.2.1" idb-keyval: ^6.2.1 ioredis: ^5.4.2 uploadthing: ^7.4.4 peerDependenciesMeta: - '@azure/app-configuration': + "@azure/app-configuration": optional: true - '@azure/cosmos': + "@azure/cosmos": optional: true - '@azure/data-tables': + "@azure/data-tables": optional: true - '@azure/identity': + "@azure/identity": optional: true - '@azure/keyvault-secrets': + "@azure/keyvault-secrets": optional: true - '@azure/storage-blob': + "@azure/storage-blob": optional: true - '@capacitor/preferences': + "@capacitor/preferences": optional: true - '@deno/kv': + "@deno/kv": optional: true - '@netlify/blobs': + "@netlify/blobs": optional: true - '@planetscale/database': + "@planetscale/database": optional: true - '@upstash/redis': + "@upstash/redis": optional: true - '@vercel/blob': + "@vercel/blob": optional: true - '@vercel/functions': + "@vercel/functions": optional: true - '@vercel/kv': + "@vercel/kv": optional: true aws4fetch: optional: true @@ -6494,218 +10912,350 @@ packages: optional: true until-async@3.0.2: - resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} + resolution: + { + integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==, + } update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + resolution: + { + integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==, + } hasBin: true peerDependencies: - browserslist: '>= 4.21.0' + browserslist: ">= 4.21.0" uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + resolution: + { + integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, + } use-callback-ref@1.3.3: - resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==, + } + engines: { node: ">=10" } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true use-sidecar@1.1.3: - resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==, + } + engines: { node: ">=10" } peerDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: - '@types/react': + "@types/react": optional: true use-sync-external-store@1.2.0: - resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + resolution: + { + integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==, + } peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 use-sync-external-store@1.4.0: - resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==} + resolution: + { + integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==, + } peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 utf-8-validate@5.0.10: - resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} - engines: {node: '>=6.14.2'} + resolution: + { + integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==, + } + engines: { node: ">=6.14.2" } utf-8-validate@6.0.6: - resolution: {integrity: sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==} - engines: {node: '>=6.14.2'} + resolution: + { + integrity: sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==, + } + engines: { node: ">=6.14.2" } util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + resolution: + { + integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, + } util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + resolution: + { + integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==, + } uuid@14.0.1: - resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==} + resolution: + { + integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==, + } hasBin: true uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + resolution: + { + integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==, + } deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@9.0.1: - resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + resolution: + { + integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==, + } deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + resolution: + { + integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==, + } valibot@1.4.2: - resolution: {integrity: sha512-gjdCvJ6d3RyHAneqxMYMW9QMCwYMb3jpOO0IyHZV1bnRHFBHrX3VkIILt5XYR0WhwHiH7Mty8ovuPZ/O3gamrg==} + resolution: + { + integrity: sha512-gjdCvJ6d3RyHAneqxMYMW9QMCwYMb3jpOO0IyHZV1bnRHFBHrX3VkIILt5XYR0WhwHiH7Mty8ovuPZ/O3gamrg==, + } peerDependencies: - typescript: '>=5' + typescript: ">=5" peerDependenciesMeta: typescript: optional: true valtio@1.13.2: - resolution: {integrity: sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A==} - engines: {node: '>=12.20.0'} + resolution: + { + integrity: sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A==, + } + engines: { node: ">=12.20.0" } peerDependencies: - '@types/react': 19.1.2 - react: '>=16.8' + "@types/react": 19.1.2 + react: ">=16.8" peerDependenciesMeta: - '@types/react': + "@types/react": optional: true react: optional: true vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==, + } + engines: { node: ">= 0.8" } vfile-location@5.0.3: - resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} + resolution: + { + integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==, + } vfile-message@4.0.3: - resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + resolution: + { + integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==, + } vfile@6.0.3: - resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + resolution: + { + integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==, + } viem@2.23.2: - resolution: {integrity: sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==} + resolution: + { + integrity: sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true viem@2.38.3: - resolution: {integrity: sha512-By2TutLv07iNHHtWqHHzjGipevYsfGqT7KQbGEmqLco1qTJxKnvBbSviqiu6/v/9REV6Q/FpmIxf2Z7/l5AbcQ==} + resolution: + { + integrity: sha512-By2TutLv07iNHHtWqHHzjGipevYsfGqT7KQbGEmqLco1qTJxKnvBbSviqiu6/v/9REV6Q/FpmIxf2Z7/l5AbcQ==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true viem@2.51.0: - resolution: {integrity: sha512-8C0Ca+eEapXE29vHMUW59NqKENl1X4s9P6xSNC9Nvw6EvAeAhn/LNUlgztk6TOw7KN1Gzz5a/n9Wv4okUfmY9g==} + resolution: + { + integrity: sha512-8C0Ca+eEapXE29vHMUW59NqKENl1X4s9P6xSNC9Nvw6EvAeAhn/LNUlgztk6TOw7KN1Gzz5a/n9Wv4okUfmY9g==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true viem@2.54.1: - resolution: {integrity: sha512-QRC3GBSnQit4pbb0sSBHRD9WYTPAffvhOqdqp8LgkRRktXZq8dePezZM/ZIkFwluLT7fMP90908goHQbtcga2A==} + resolution: + { + integrity: sha512-QRC3GBSnQit4pbb0sSBHRD9WYTPAffvhOqdqp8LgkRRktXZq8dePezZM/ZIkFwluLT7fMP90908goHQbtcga2A==, + } peerDependencies: - typescript: '>=5.0.4' + typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true wagmi@2.19.5: - resolution: {integrity: sha512-RQUfKMv6U+EcSNNGiPbdkDtJwtuFxZWLmvDiQmjjBgkuPulUwDJsKhi7gjynzJdsx2yDqhHCXkKsbbfbIsHfcQ==} + resolution: + { + integrity: sha512-RQUfKMv6U+EcSNNGiPbdkDtJwtuFxZWLmvDiQmjjBgkuPulUwDJsKhi7gjynzJdsx2yDqhHCXkKsbbfbIsHfcQ==, + } peerDependencies: - '@tanstack/react-query': '>=5.0.0' - react: '>=18' - typescript: '>=5.0.4' + "@tanstack/react-query": ">=5.0.0" + react: ">=18" + typescript: ">=5.0.4" viem: 2.x peerDependenciesMeta: typescript: optional: true wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + resolution: + { + integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==, + } web-namespaces@2.0.1: - resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + resolution: + { + integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==, + } web-streams-polyfill@3.3.3: - resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==, + } + engines: { node: ">= 8" } web-vitals@5.3.0: - resolution: {integrity: sha512-q6LWsLatGYZp5VGBIOvbTj6JBV2nOmC8KvWztXBmwJcfFAzhwKwbOxhUH306XY3CcaZDUlSmSuNPBsCn0bFu+g==} + resolution: + { + integrity: sha512-q6LWsLatGYZp5VGBIOvbTj6JBV2nOmC8KvWztXBmwJcfFAzhwKwbOxhUH306XY3CcaZDUlSmSuNPBsCn0bFu+g==, + } webextension-polyfill@0.10.0: - resolution: {integrity: sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==} + resolution: + { + integrity: sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==, + } webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + resolution: + { + integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, + } whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + resolution: + { + integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, + } which-boxed-primitive@1.1.1: - resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==, + } + engines: { node: ">= 0.4" } which-builtin-type@1.2.1: - resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==, + } + engines: { node: ">= 0.4" } which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==, + } + engines: { node: ">= 0.4" } which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + resolution: + { + integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==, + } which-typed-array@1.1.22: - resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==, + } + engines: { node: ">= 0.4" } which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, + } + engines: { node: ">= 8" } hasBin: true word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==, + } + engines: { node: ">=0.10.0" } wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} + 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'} + resolution: + { + integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, + } + engines: { node: ">=10" } wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + resolution: + { + integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, + } ws@7.5.11: - resolution: {integrity: sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==} - engines: {node: '>=8.3.0'} + resolution: + { + integrity: sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==, + } + engines: { node: ">=8.3.0" } peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -6716,11 +11266,14 @@ packages: optional: true ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==, + } + engines: { node: ">=10.0.0" } peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true @@ -6728,11 +11281,14 @@ packages: optional: true ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==, + } + engines: { node: ">=10.0.0" } peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true @@ -6740,11 +11296,14 @@ packages: optional: true ws@8.20.1: - resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==, + } + engines: { node: ">=10.0.0" } peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true @@ -6752,11 +11311,14 @@ packages: optional: true ws@8.21.0: - resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==, + } + engines: { node: ">=10.0.0" } peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true @@ -6764,77 +11326,128 @@ packages: optional: true xmlhttprequest-ssl@2.1.2: - resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} - engines: {node: '>=0.4.0'} + resolution: + { + integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==, + } + engines: { node: ">=0.4.0" } xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} + resolution: + { + integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, + } + engines: { node: ">=0.4" } y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + resolution: + { + integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==, + } y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, + } + engines: { node: ">=10" } yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + resolution: + { + integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==, + } yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==, + } + engines: { node: ">=6" } yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} + 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'} + 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'} + resolution: + { + integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==, + } + engines: { node: ">=12" } yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==, + } + engines: { node: ">=6" } yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, + } + engines: { node: ">=10" } zod-to-json-schema@3.25.2: - resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + resolution: + { + integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==, + } peerDependencies: zod: ^3.25.28 || ^4 zod-validation-error@4.0.2: - resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} - engines: {node: '>=18.0.0'} + resolution: + { + integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==, + } + engines: { node: ">=18.0.0" } peerDependencies: zod: ^3.25.0 || ^4.0.0 zod@3.22.4: - resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + resolution: + { + integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==, + } zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + resolution: + { + integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==, + } zod@4.4.3: - resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + resolution: + { + integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==, + } zustand@5.0.0: - resolution: {integrity: sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==} - engines: {node: '>=12.20.0'} + resolution: + { + integrity: sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==, + } + engines: { node: ">=12.20.0" } peerDependencies: - '@types/react': 19.1.2 - immer: '>=9.0.6' - react: '>=18.0.0' - use-sync-external-store: '>=1.2.0' + "@types/react": 19.1.2 + immer: ">=9.0.6" + react: ">=18.0.0" + use-sync-external-store: ">=1.2.0" peerDependenciesMeta: - '@types/react': + "@types/react": optional: true immer: optional: true @@ -6844,15 +11457,18 @@ packages: optional: true zustand@5.0.14: - resolution: {integrity: sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==} - engines: {node: '>=12.20.0'} + resolution: + { + integrity: sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==, + } + engines: { node: ">=12.20.0" } peerDependencies: - '@types/react': 19.1.2 - immer: '>=9.0.6' - react: '>=18.0.0' - use-sync-external-store: '>=1.2.0' + "@types/react": 19.1.2 + immer: ">=9.0.6" + react: ">=18.0.0" + use-sync-external-store: ">=1.2.0" peerDependenciesMeta: - '@types/react': + "@types/react": optional: true immer: optional: true @@ -6862,15 +11478,18 @@ packages: optional: true zustand@5.0.3: - resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} - engines: {node: '>=12.20.0'} + resolution: + { + integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==, + } + engines: { node: ">=12.20.0" } peerDependencies: - '@types/react': 19.1.2 - immer: '>=9.0.6' - react: '>=18.0.0' - use-sync-external-store: '>=1.2.0' + "@types/react": 19.1.2 + immer: ">=9.0.6" + react: ">=18.0.0" + use-sync-external-store: ">=1.2.0" peerDependenciesMeta: - '@types/react': + "@types/react": optional: true immer: optional: true @@ -6880,40 +11499,42 @@ packages: optional: true zwitch@2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + resolution: + { + integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==, + } snapshots: - - '@0no-co/graphql.web@1.3.2(graphql@16.14.2)': + "@0no-co/graphql.web@1.3.2(graphql@16.14.2)": optionalDependencies: graphql: 16.14.2 - '@0no-co/graphqlsp@1.17.3(graphql@16.14.2)(typescript@5.9.3)': + "@0no-co/graphqlsp@1.17.3(graphql@16.14.2)(typescript@5.9.3)": dependencies: - '@gql.tada/internal': 1.2.1(graphql@16.14.2)(typescript@5.9.3) + "@gql.tada/internal": 1.2.1(graphql@16.14.2)(typescript@5.9.3) graphql: 16.14.2 typescript: 5.9.3 - '@aave/account@0.2.0(react-dom@19.2.2(react@19.2.2))(react@19.2.2)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))': + "@aave/account@0.2.0(react-dom@19.2.2(react@19.2.2))(react@19.2.2)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))": optionalDependencies: react: 19.2.2 react-dom: 19.2.2(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) wagmi: 2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76) - '@adraffy/ens-normalize@1.11.1': {} + "@adraffy/ens-normalize@1.11.1": {} - '@alloc/quick-lru@5.2.0': {} + "@alloc/quick-lru@5.2.0": {} - '@antfu/ni@23.3.1': {} + "@antfu/ni@23.3.1": {} - '@avail-project/nexus-core@2.4.1(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + "@avail-project/nexus-core@2.5.0(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)": dependencies: - '@avail-project/nexus-types': 0.1.25(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@opentelemetry/api-logs': 0.219.0 - '@opentelemetry/exporter-logs-otlp-http': 0.219.0(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-logs': 0.219.0(@opentelemetry/api@1.9.1) + "@avail-project/nexus-types": 0.1.25(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@opentelemetry/api-logs": 0.219.0 + "@opentelemetry/exporter-logs-otlp-http": 0.219.0(@opentelemetry/api@1.9.1) + "@opentelemetry/resources": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/sdk-logs": 0.219.0(@opentelemetry/api@1.9.1) axios: 1.18.1 decimal.js: 10.6.0 es-toolkit: 1.46.1 @@ -6921,9 +11542,9 @@ snapshots: viem: 2.51.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) zod: 4.4.3 transitivePeerDependencies: - - '@gql.tada/svelte-support' - - '@gql.tada/vue-support' - - '@opentelemetry/api' + - "@gql.tada/svelte-support" + - "@gql.tada/vue-support" + - "@opentelemetry/api" - bufferutil - debug - encoding @@ -6931,13 +11552,13 @@ snapshots: - typescript - utf-8-validate - '@avail-project/nexus-core@2.4.1(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': + "@avail-project/nexus-core@2.5.0(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)": dependencies: - '@avail-project/nexus-types': 0.1.25(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.4.3) - '@opentelemetry/api-logs': 0.219.0 - '@opentelemetry/exporter-logs-otlp-http': 0.219.0(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-logs': 0.219.0(@opentelemetry/api@1.9.1) + "@avail-project/nexus-types": 0.1.25(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.4.3) + "@opentelemetry/api-logs": 0.219.0 + "@opentelemetry/exporter-logs-otlp-http": 0.219.0(@opentelemetry/api@1.9.1) + "@opentelemetry/resources": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/sdk-logs": 0.219.0(@opentelemetry/api@1.9.1) axios: 1.18.1 decimal.js: 10.6.0 es-toolkit: 1.46.1 @@ -6945,9 +11566,9 @@ snapshots: viem: 2.51.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.4.3) zod: 4.4.3 transitivePeerDependencies: - - '@gql.tada/svelte-support' - - '@gql.tada/vue-support' - - '@opentelemetry/api' + - "@gql.tada/svelte-support" + - "@gql.tada/vue-support" + - "@opentelemetry/api" - bufferutil - debug - encoding @@ -6955,52 +11576,52 @@ snapshots: - typescript - utf-8-validate - '@avail-project/nexus-types@0.1.25(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': + "@avail-project/nexus-types@0.1.25(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@mayanfinance/swap-sdk': 13.3.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@mayanfinance/swap-sdk": 13.3.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) viem: 2.54.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) zod: 4.4.3 transitivePeerDependencies: - - '@gql.tada/svelte-support' - - '@gql.tada/vue-support' + - "@gql.tada/svelte-support" + - "@gql.tada/vue-support" - bufferutil - encoding - typescript - utf-8-validate - '@avail-project/nexus-types@0.1.25(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.4.3)': + "@avail-project/nexus-types@0.1.25(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.4.3)": dependencies: - '@mayanfinance/swap-sdk': 13.3.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@mayanfinance/swap-sdk": 13.3.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) viem: 2.54.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.4.3) zod: 4.4.3 transitivePeerDependencies: - - '@gql.tada/svelte-support' - - '@gql.tada/vue-support' + - "@gql.tada/svelte-support" + - "@gql.tada/vue-support" - bufferutil - encoding - typescript - utf-8-validate - '@babel/code-frame@7.29.7': + "@babel/code-frame@7.29.7": dependencies: - '@babel/helper-validator-identifier': 7.29.7 + "@babel/helper-validator-identifier": 7.29.7 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.29.7': {} + "@babel/compat-data@7.29.7": {} - '@babel/core@7.29.7': + "@babel/core@7.29.7": dependencies: - '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 - '@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.7 - '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@5.5.0) - '@babel/types': 7.29.7 - '@jridgewell/remapping': 2.3.5 + "@babel/code-frame": 7.29.7 + "@babel/generator": 7.29.7 + "@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.7 + "@babel/template": 7.29.7 + "@babel/traverse": 7.29.7(supports-color@5.5.0) + "@babel/types": 7.29.7 + "@jridgewell/remapping": 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3(supports-color@5.5.0) gensync: 1.0.0-beta.2 @@ -7009,151 +11630,151 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.7': + "@babel/generator@7.29.7": dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 + "@babel/parser": 7.29.7 + "@babel/types": 7.29.7 + "@jridgewell/gen-mapping": 0.3.13 + "@jridgewell/trace-mapping": 0.3.31 jsesc: 3.1.0 - '@babel/helper-annotate-as-pure@7.29.7': + "@babel/helper-annotate-as-pure@7.29.7": dependencies: - '@babel/types': 7.29.7 + "@babel/types": 7.29.7 - '@babel/helper-compilation-targets@7.29.7': + "@babel/helper-compilation-targets@7.29.7": dependencies: - '@babel/compat-data': 7.29.7 - '@babel/helper-validator-option': 7.29.7 + "@babel/compat-data": 7.29.7 + "@babel/helper-validator-option": 7.29.7 browserslist: 4.28.4 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7)': + "@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7)": dependencies: - '@babel/core': 7.29.7 - '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-member-expression-to-functions': 7.29.7 - '@babel/helper-optimise-call-expression': 7.29.7 - '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7) - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@5.5.0) + "@babel/core": 7.29.7 + "@babel/helper-annotate-as-pure": 7.29.7 + "@babel/helper-member-expression-to-functions": 7.29.7 + "@babel/helper-optimise-call-expression": 7.29.7 + "@babel/helper-replace-supers": 7.29.7(@babel/core@7.29.7) + "@babel/helper-skip-transparent-expression-wrappers": 7.29.7 + "@babel/traverse": 7.29.7(supports-color@5.5.0) semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-globals@7.29.7': {} + "@babel/helper-globals@7.29.7": {} - '@babel/helper-member-expression-to-functions@7.29.7': + "@babel/helper-member-expression-to-functions@7.29.7": dependencies: - '@babel/traverse': 7.29.7(supports-color@5.5.0) - '@babel/types': 7.29.7 + "@babel/traverse": 7.29.7(supports-color@5.5.0) + "@babel/types": 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.29.7(supports-color@5.5.0)': + "@babel/helper-module-imports@7.29.7(supports-color@5.5.0)": dependencies: - '@babel/traverse': 7.29.7(supports-color@5.5.0) - '@babel/types': 7.29.7 + "@babel/traverse": 7.29.7(supports-color@5.5.0) + "@babel/types": 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + "@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(supports-color@5.5.0) - '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@5.5.0) + "@babel/core": 7.29.7 + "@babel/helper-module-imports": 7.29.7(supports-color@5.5.0) + "@babel/helper-validator-identifier": 7.29.7 + "@babel/traverse": 7.29.7(supports-color@5.5.0) transitivePeerDependencies: - supports-color - '@babel/helper-optimise-call-expression@7.29.7': + "@babel/helper-optimise-call-expression@7.29.7": dependencies: - '@babel/types': 7.29.7 + "@babel/types": 7.29.7 - '@babel/helper-plugin-utils@7.29.7': {} + "@babel/helper-plugin-utils@7.29.7": {} - '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7)': + "@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7)": dependencies: - '@babel/core': 7.29.7 - '@babel/helper-member-expression-to-functions': 7.29.7 - '@babel/helper-optimise-call-expression': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@5.5.0) + "@babel/core": 7.29.7 + "@babel/helper-member-expression-to-functions": 7.29.7 + "@babel/helper-optimise-call-expression": 7.29.7 + "@babel/traverse": 7.29.7(supports-color@5.5.0) transitivePeerDependencies: - supports-color - '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + "@babel/helper-skip-transparent-expression-wrappers@7.29.7": dependencies: - '@babel/traverse': 7.29.7(supports-color@5.5.0) - '@babel/types': 7.29.7 + "@babel/traverse": 7.29.7(supports-color@5.5.0) + "@babel/types": 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-string-parser@7.29.7': {} + "@babel/helper-string-parser@7.29.7": {} - '@babel/helper-validator-identifier@7.29.7': {} + "@babel/helper-validator-identifier@7.29.7": {} - '@babel/helper-validator-option@7.29.7': {} + "@babel/helper-validator-option@7.29.7": {} - '@babel/helpers@7.29.7': + "@babel/helpers@7.29.7": dependencies: - '@babel/template': 7.29.7 - '@babel/types': 7.29.7 + "@babel/template": 7.29.7 + "@babel/types": 7.29.7 - '@babel/parser@7.29.7': + "@babel/parser@7.29.7": dependencies: - '@babel/types': 7.29.7 + "@babel/types": 7.29.7 - '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)': + "@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)": dependencies: - '@babel/core': 7.29.7 - '@babel/helper-plugin-utils': 7.29.7 + "@babel/core": 7.29.7 + "@babel/helper-plugin-utils": 7.29.7 - '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7)': + "@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7)": dependencies: - '@babel/core': 7.29.7 - '@babel/helper-plugin-utils': 7.29.7 + "@babel/core": 7.29.7 + "@babel/helper-plugin-utils": 7.29.7 - '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7)': + "@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7)": dependencies: - '@babel/core': 7.29.7 - '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 - '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7) + "@babel/core": 7.29.7 + "@babel/helper-annotate-as-pure": 7.29.7 + "@babel/helper-create-class-features-plugin": 7.29.7(@babel/core@7.29.7) + "@babel/helper-plugin-utils": 7.29.7 + "@babel/helper-skip-transparent-expression-wrappers": 7.29.7 + "@babel/plugin-syntax-typescript": 7.29.7(@babel/core@7.29.7) transitivePeerDependencies: - supports-color - '@babel/runtime@7.29.7': {} + "@babel/runtime@7.29.7": {} - '@babel/template@7.29.7': + "@babel/template@7.29.7": dependencies: - '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + "@babel/code-frame": 7.29.7 + "@babel/parser": 7.29.7 + "@babel/types": 7.29.7 - '@babel/traverse@7.29.7(supports-color@5.5.0)': + "@babel/traverse@7.29.7(supports-color@5.5.0)": dependencies: - '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 - '@babel/helper-globals': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/template': 7.29.7 - '@babel/types': 7.29.7 + "@babel/code-frame": 7.29.7 + "@babel/generator": 7.29.7 + "@babel/helper-globals": 7.29.7 + "@babel/parser": 7.29.7 + "@babel/template": 7.29.7 + "@babel/types": 7.29.7 debug: 4.4.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color - '@babel/types@7.29.7': + "@babel/types@7.29.7": dependencies: - '@babel/helper-string-parser': 7.29.7 - '@babel/helper-validator-identifier': 7.29.7 + "@babel/helper-string-parser": 7.29.7 + "@babel/helper-validator-identifier": 7.29.7 - '@base-org/account@2.4.0(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(zod@4.4.3)': + "@base-org/account@2.4.0(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@coinbase/cdp-sdk': 1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@noble/hashes': 1.4.0 + "@coinbase/cdp-sdk": 1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@noble/hashes": 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 idb-keyval: 6.2.1 @@ -7162,7 +11783,7 @@ snapshots: viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) zustand: 5.0.3(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)) transitivePeerDependencies: - - '@types/react' + - "@types/react" - bufferutil - debug - fastestsmallesttextencoderdecoder @@ -7174,10 +11795,10 @@ snapshots: - utf-8-validate - zod - '@base-org/account@2.4.0(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(zod@3.25.76)': + "@base-org/account@2.4.0(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: - '@coinbase/cdp-sdk': 1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@noble/hashes': 1.4.0 + "@coinbase/cdp-sdk": 1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@noble/hashes": 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 idb-keyval: 6.2.1 @@ -7186,7 +11807,7 @@ snapshots: viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zustand: 5.0.3(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)) transitivePeerDependencies: - - '@types/react' + - "@types/react" - bufferutil - debug - fastestsmallesttextencoderdecoder @@ -7198,11 +11819,11 @@ snapshots: - utf-8-validate - zod - '@coinbase/cdp-sdk@1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + "@coinbase/cdp-sdk@1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)": dependencies: - '@solana-program/system': 0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@solana-program/token': 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@solana/kit': 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@solana-program/system": 0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) + "@solana-program/token": 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) + "@solana/kit": 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) abitype: 1.0.6(typescript@5.9.3)(zod@3.25.76) axios: 1.18.1 axios-retry: 4.5.0(axios@1.18.1) @@ -7220,11 +11841,11 @@ snapshots: - typescript - utf-8-validate - '@coinbase/cdp-sdk@1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': + "@coinbase/cdp-sdk@1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)": dependencies: - '@solana-program/system': 0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@solana-program/token': 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@solana/kit': 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@solana-program/system": 0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) + "@solana-program/token": 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) + "@solana/kit": 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) abitype: 1.0.6(typescript@5.9.3)(zod@3.25.76) axios: 1.18.1 axios-retry: 4.5.0(axios@1.18.1) @@ -7242,7 +11863,7 @@ snapshots: - typescript - utf-8-validate - '@coinbase/wallet-sdk@3.9.3': + "@coinbase/wallet-sdk@3.9.3": dependencies: bn.js: 5.2.4 buffer: 6.0.3 @@ -7256,9 +11877,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@coinbase/wallet-sdk@4.3.6(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(zod@4.4.3)': + "@coinbase/wallet-sdk@4.3.6(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@noble/hashes': 1.4.0 + "@noble/hashes": 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 idb-keyval: 6.2.1 @@ -7267,7 +11888,7 @@ snapshots: viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) zustand: 5.0.3(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)) transitivePeerDependencies: - - '@types/react' + - "@types/react" - bufferutil - immer - react @@ -7276,9 +11897,9 @@ snapshots: - utf-8-validate - zod - '@coinbase/wallet-sdk@4.3.6(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(zod@3.25.76)': + "@coinbase/wallet-sdk@4.3.6(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: - '@noble/hashes': 1.4.0 + "@noble/hashes": 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 idb-keyval: 6.2.1 @@ -7287,7 +11908,7 @@ snapshots: viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zustand: 5.0.3(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)) transitivePeerDependencies: - - '@types/react' + - "@types/react" - bufferutil - immer - react @@ -7296,233 +11917,233 @@ snapshots: - utf-8-validate - zod - '@cspotcode/source-map-support@0.8.1': + "@cspotcode/source-map-support@0.8.1": dependencies: - '@jridgewell/trace-mapping': 0.3.9 + "@jridgewell/trace-mapping": 0.3.9 - '@ecies/ciphers@0.2.6(@noble/ciphers@1.3.0)': + "@ecies/ciphers@0.2.6(@noble/ciphers@1.3.0)": dependencies: - '@noble/ciphers': 1.3.0 + "@noble/ciphers": 1.3.0 - '@emnapi/core@1.10.0': + "@emnapi/core@1.10.0": dependencies: - '@emnapi/wasi-threads': 1.2.1 + "@emnapi/wasi-threads": 1.2.1 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.10.0': + "@emnapi/runtime@1.10.0": dependencies: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.11.1': + "@emnapi/runtime@1.11.1": dependencies: tslib: 2.8.1 optional: true - '@emnapi/wasi-threads@1.2.1': + "@emnapi/wasi-threads@1.2.1": dependencies: tslib: 2.8.1 optional: true - '@emotion/is-prop-valid@0.8.8': + "@emotion/is-prop-valid@0.8.8": dependencies: - '@emotion/memoize': 0.7.4 + "@emotion/memoize": 0.7.4 optional: true - '@emotion/is-prop-valid@1.4.0': + "@emotion/is-prop-valid@1.4.0": dependencies: - '@emotion/memoize': 0.9.0 + "@emotion/memoize": 0.9.0 - '@emotion/memoize@0.7.4': + "@emotion/memoize@0.7.4": optional: true - '@emotion/memoize@0.9.0': {} + "@emotion/memoize@0.9.0": {} - '@emotion/stylis@0.8.5': {} + "@emotion/stylis@0.8.5": {} - '@emotion/unitless@0.7.5': {} + "@emotion/unitless@0.7.5": {} - '@esbuild/aix-ppc64@0.25.12': + "@esbuild/aix-ppc64@0.25.12": optional: true - '@esbuild/aix-ppc64@0.28.1': + "@esbuild/aix-ppc64@0.28.1": optional: true - '@esbuild/android-arm64@0.25.12': + "@esbuild/android-arm64@0.25.12": optional: true - '@esbuild/android-arm64@0.28.1': + "@esbuild/android-arm64@0.28.1": optional: true - '@esbuild/android-arm@0.25.12': + "@esbuild/android-arm@0.25.12": optional: true - '@esbuild/android-arm@0.28.1': + "@esbuild/android-arm@0.28.1": optional: true - '@esbuild/android-x64@0.25.12': + "@esbuild/android-x64@0.25.12": optional: true - '@esbuild/android-x64@0.28.1': + "@esbuild/android-x64@0.28.1": optional: true - '@esbuild/darwin-arm64@0.25.12': + "@esbuild/darwin-arm64@0.25.12": optional: true - '@esbuild/darwin-arm64@0.28.1': + "@esbuild/darwin-arm64@0.28.1": optional: true - '@esbuild/darwin-x64@0.25.12': + "@esbuild/darwin-x64@0.25.12": optional: true - '@esbuild/darwin-x64@0.28.1': + "@esbuild/darwin-x64@0.28.1": optional: true - '@esbuild/freebsd-arm64@0.25.12': + "@esbuild/freebsd-arm64@0.25.12": optional: true - '@esbuild/freebsd-arm64@0.28.1': + "@esbuild/freebsd-arm64@0.28.1": optional: true - '@esbuild/freebsd-x64@0.25.12': + "@esbuild/freebsd-x64@0.25.12": optional: true - '@esbuild/freebsd-x64@0.28.1': + "@esbuild/freebsd-x64@0.28.1": optional: true - '@esbuild/linux-arm64@0.25.12': + "@esbuild/linux-arm64@0.25.12": optional: true - '@esbuild/linux-arm64@0.28.1': + "@esbuild/linux-arm64@0.28.1": optional: true - '@esbuild/linux-arm@0.25.12': + "@esbuild/linux-arm@0.25.12": optional: true - '@esbuild/linux-arm@0.28.1': + "@esbuild/linux-arm@0.28.1": optional: true - '@esbuild/linux-ia32@0.25.12': + "@esbuild/linux-ia32@0.25.12": optional: true - '@esbuild/linux-ia32@0.28.1': + "@esbuild/linux-ia32@0.28.1": optional: true - '@esbuild/linux-loong64@0.25.12': + "@esbuild/linux-loong64@0.25.12": optional: true - '@esbuild/linux-loong64@0.28.1': + "@esbuild/linux-loong64@0.28.1": optional: true - '@esbuild/linux-mips64el@0.25.12': + "@esbuild/linux-mips64el@0.25.12": optional: true - '@esbuild/linux-mips64el@0.28.1': + "@esbuild/linux-mips64el@0.28.1": optional: true - '@esbuild/linux-ppc64@0.25.12': + "@esbuild/linux-ppc64@0.25.12": optional: true - '@esbuild/linux-ppc64@0.28.1': + "@esbuild/linux-ppc64@0.28.1": optional: true - '@esbuild/linux-riscv64@0.25.12': + "@esbuild/linux-riscv64@0.25.12": optional: true - '@esbuild/linux-riscv64@0.28.1': + "@esbuild/linux-riscv64@0.28.1": optional: true - '@esbuild/linux-s390x@0.25.12': + "@esbuild/linux-s390x@0.25.12": optional: true - '@esbuild/linux-s390x@0.28.1': + "@esbuild/linux-s390x@0.28.1": optional: true - '@esbuild/linux-x64@0.25.12': + "@esbuild/linux-x64@0.25.12": optional: true - '@esbuild/linux-x64@0.28.1': + "@esbuild/linux-x64@0.28.1": optional: true - '@esbuild/netbsd-arm64@0.25.12': + "@esbuild/netbsd-arm64@0.25.12": optional: true - '@esbuild/netbsd-arm64@0.28.1': + "@esbuild/netbsd-arm64@0.28.1": optional: true - '@esbuild/netbsd-x64@0.25.12': + "@esbuild/netbsd-x64@0.25.12": optional: true - '@esbuild/netbsd-x64@0.28.1': + "@esbuild/netbsd-x64@0.28.1": optional: true - '@esbuild/openbsd-arm64@0.25.12': + "@esbuild/openbsd-arm64@0.25.12": optional: true - '@esbuild/openbsd-arm64@0.28.1': + "@esbuild/openbsd-arm64@0.28.1": optional: true - '@esbuild/openbsd-x64@0.25.12': + "@esbuild/openbsd-x64@0.25.12": optional: true - '@esbuild/openbsd-x64@0.28.1': + "@esbuild/openbsd-x64@0.28.1": optional: true - '@esbuild/openharmony-arm64@0.25.12': + "@esbuild/openharmony-arm64@0.25.12": optional: true - '@esbuild/openharmony-arm64@0.28.1': + "@esbuild/openharmony-arm64@0.28.1": optional: true - '@esbuild/sunos-x64@0.25.12': + "@esbuild/sunos-x64@0.25.12": optional: true - '@esbuild/sunos-x64@0.28.1': + "@esbuild/sunos-x64@0.28.1": optional: true - '@esbuild/win32-arm64@0.25.12': + "@esbuild/win32-arm64@0.25.12": optional: true - '@esbuild/win32-arm64@0.28.1': + "@esbuild/win32-arm64@0.28.1": optional: true - '@esbuild/win32-ia32@0.25.12': + "@esbuild/win32-ia32@0.25.12": optional: true - '@esbuild/win32-ia32@0.28.1': + "@esbuild/win32-ia32@0.28.1": optional: true - '@esbuild/win32-x64@0.25.12': + "@esbuild/win32-x64@0.25.12": optional: true - '@esbuild/win32-x64@0.28.1': + "@esbuild/win32-x64@0.28.1": optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))': + "@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))": dependencies: eslint: 9.39.4(jiti@2.7.0) eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.2': {} + "@eslint-community/regexpp@4.12.2": {} - '@eslint/config-array@0.21.2': + "@eslint/config-array@0.21.2": dependencies: - '@eslint/object-schema': 2.1.7 + "@eslint/object-schema": 2.1.7 debug: 4.4.3(supports-color@5.5.0) minimatch: 3.1.5 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.4.2': + "@eslint/config-helpers@0.4.2": dependencies: - '@eslint/core': 0.17.0 + "@eslint/core": 0.17.0 - '@eslint/core@0.17.0': + "@eslint/core@0.17.0": dependencies: - '@types/json-schema': 7.0.15 + "@types/json-schema": 7.0.15 - '@eslint/eslintrc@3.3.5': + "@eslint/eslintrc@3.3.5": dependencies: ajv: 6.15.0 debug: 4.4.3(supports-color@5.5.0) @@ -7536,301 +12157,301 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.39.4': {} + "@eslint/js@9.39.4": {} - '@eslint/object-schema@2.1.7': {} + "@eslint/object-schema@2.1.7": {} - '@eslint/plugin-kit@0.4.1': + "@eslint/plugin-kit@0.4.1": dependencies: - '@eslint/core': 0.17.0 + "@eslint/core": 0.17.0 levn: 0.4.1 - '@ethereumjs/common@3.2.0': + "@ethereumjs/common@3.2.0": dependencies: - '@ethereumjs/util': 8.1.0 + "@ethereumjs/util": 8.1.0 crc-32: 1.2.2 - '@ethereumjs/rlp@4.0.1': {} + "@ethereumjs/rlp@4.0.1": {} - '@ethereumjs/tx@4.2.0': + "@ethereumjs/tx@4.2.0": dependencies: - '@ethereumjs/common': 3.2.0 - '@ethereumjs/rlp': 4.0.1 - '@ethereumjs/util': 8.1.0 + "@ethereumjs/common": 3.2.0 + "@ethereumjs/rlp": 4.0.1 + "@ethereumjs/util": 8.1.0 ethereum-cryptography: 2.2.1 - '@ethereumjs/util@8.1.0': + "@ethereumjs/util@8.1.0": dependencies: - '@ethereumjs/rlp': 4.0.1 + "@ethereumjs/rlp": 4.0.1 ethereum-cryptography: 2.2.1 micro-ftch: 0.3.1 - '@floating-ui/core@1.7.5': + "@floating-ui/core@1.7.5": dependencies: - '@floating-ui/utils': 0.2.11 + "@floating-ui/utils": 0.2.11 - '@floating-ui/dom@1.7.6': + "@floating-ui/dom@1.7.6": dependencies: - '@floating-ui/core': 1.7.5 - '@floating-ui/utils': 0.2.11 + "@floating-ui/core": 1.7.5 + "@floating-ui/utils": 0.2.11 - '@floating-ui/react-dom@2.1.8(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@floating-ui/react-dom@2.1.8(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@floating-ui/dom': 1.7.6 + "@floating-ui/dom": 1.7.6 react: 19.2.2 react-dom: 19.2.2(react@19.2.2) - '@floating-ui/utils@0.2.11': {} + "@floating-ui/utils@0.2.11": {} - '@gemini-wallet/core@0.3.2(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))': + "@gemini-wallet/core@0.3.2(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))": dependencies: - '@metamask/rpc-errors': 7.0.2 + "@metamask/rpc-errors": 7.0.2 eventemitter3: 5.0.1 viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) transitivePeerDependencies: - supports-color - '@gemini-wallet/core@0.3.2(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))': + "@gemini-wallet/core@0.3.2(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))": dependencies: - '@metamask/rpc-errors': 7.0.2 + "@metamask/rpc-errors": 7.0.2 eventemitter3: 5.0.1 viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) transitivePeerDependencies: - supports-color - '@gql.tada/cli-utils@1.9.2(@0no-co/graphqlsp@1.17.3(graphql@16.14.2)(typescript@5.9.3))(graphql@16.14.2)(typescript@5.9.3)': + "@gql.tada/cli-utils@1.9.2(@0no-co/graphqlsp@1.17.3(graphql@16.14.2)(typescript@5.9.3))(graphql@16.14.2)(typescript@5.9.3)": dependencies: - '@0no-co/graphqlsp': 1.17.3(graphql@16.14.2)(typescript@5.9.3) - '@gql.tada/internal': 1.2.1(graphql@16.14.2)(typescript@5.9.3) + "@0no-co/graphqlsp": 1.17.3(graphql@16.14.2)(typescript@5.9.3) + "@gql.tada/internal": 1.2.1(graphql@16.14.2)(typescript@5.9.3) graphql: 16.14.2 typescript: 5.9.3 - '@gql.tada/internal@1.2.1(graphql@16.14.2)(typescript@5.9.3)': + "@gql.tada/internal@1.2.1(graphql@16.14.2)(typescript@5.9.3)": dependencies: - '@0no-co/graphql.web': 1.3.2(graphql@16.14.2) + "@0no-co/graphql.web": 1.3.2(graphql@16.14.2) graphql: 16.14.2 typescript: 5.9.3 - '@graphql-typed-document-node/core@3.2.0(graphql@16.14.2)': + "@graphql-typed-document-node/core@3.2.0(graphql@16.14.2)": dependencies: graphql: 16.14.2 - '@hono/node-server@1.19.14(hono@4.12.27)': + "@hono/node-server@1.19.14(hono@4.12.27)": dependencies: hono: 4.12.27 - '@humanfs/core@0.19.2': + "@humanfs/core@0.19.2": dependencies: - '@humanfs/types': 0.15.0 + "@humanfs/types": 0.15.0 - '@humanfs/node@0.16.8': + "@humanfs/node@0.16.8": dependencies: - '@humanfs/core': 0.19.2 - '@humanfs/types': 0.15.0 - '@humanwhocodes/retry': 0.4.3 + "@humanfs/core": 0.19.2 + "@humanfs/types": 0.15.0 + "@humanwhocodes/retry": 0.4.3 - '@humanfs/types@0.15.0': {} + "@humanfs/types@0.15.0": {} - '@humanwhocodes/module-importer@1.0.1': {} + "@humanwhocodes/module-importer@1.0.1": {} - '@humanwhocodes/retry@0.4.3': {} + "@humanwhocodes/retry@0.4.3": {} - '@img/colour@1.1.0': + "@img/colour@1.1.0": optional: true - '@img/sharp-darwin-arm64@0.34.5': + "@img/sharp-darwin-arm64@0.34.5": optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.2.4 + "@img/sharp-libvips-darwin-arm64": 1.2.4 optional: true - '@img/sharp-darwin-x64@0.34.5': + "@img/sharp-darwin-x64@0.34.5": optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.2.4 + "@img/sharp-libvips-darwin-x64": 1.2.4 optional: true - '@img/sharp-libvips-darwin-arm64@1.2.4': + "@img/sharp-libvips-darwin-arm64@1.2.4": optional: true - '@img/sharp-libvips-darwin-x64@1.2.4': + "@img/sharp-libvips-darwin-x64@1.2.4": optional: true - '@img/sharp-libvips-linux-arm64@1.2.4': + "@img/sharp-libvips-linux-arm64@1.2.4": optional: true - '@img/sharp-libvips-linux-arm@1.2.4': + "@img/sharp-libvips-linux-arm@1.2.4": optional: true - '@img/sharp-libvips-linux-ppc64@1.2.4': + "@img/sharp-libvips-linux-ppc64@1.2.4": optional: true - '@img/sharp-libvips-linux-riscv64@1.2.4': + "@img/sharp-libvips-linux-riscv64@1.2.4": optional: true - '@img/sharp-libvips-linux-s390x@1.2.4': + "@img/sharp-libvips-linux-s390x@1.2.4": optional: true - '@img/sharp-libvips-linux-x64@1.2.4': + "@img/sharp-libvips-linux-x64@1.2.4": optional: true - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + "@img/sharp-libvips-linuxmusl-arm64@1.2.4": optional: true - '@img/sharp-libvips-linuxmusl-x64@1.2.4': + "@img/sharp-libvips-linuxmusl-x64@1.2.4": optional: true - '@img/sharp-linux-arm64@0.34.5': + "@img/sharp-linux-arm64@0.34.5": optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.2.4 + "@img/sharp-libvips-linux-arm64": 1.2.4 optional: true - '@img/sharp-linux-arm@0.34.5': + "@img/sharp-linux-arm@0.34.5": optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.2.4 + "@img/sharp-libvips-linux-arm": 1.2.4 optional: true - '@img/sharp-linux-ppc64@0.34.5': + "@img/sharp-linux-ppc64@0.34.5": optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.2.4 + "@img/sharp-libvips-linux-ppc64": 1.2.4 optional: true - '@img/sharp-linux-riscv64@0.34.5': + "@img/sharp-linux-riscv64@0.34.5": optionalDependencies: - '@img/sharp-libvips-linux-riscv64': 1.2.4 + "@img/sharp-libvips-linux-riscv64": 1.2.4 optional: true - '@img/sharp-linux-s390x@0.34.5': + "@img/sharp-linux-s390x@0.34.5": optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.2.4 + "@img/sharp-libvips-linux-s390x": 1.2.4 optional: true - '@img/sharp-linux-x64@0.34.5': + "@img/sharp-linux-x64@0.34.5": optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.2.4 + "@img/sharp-libvips-linux-x64": 1.2.4 optional: true - '@img/sharp-linuxmusl-arm64@0.34.5': + "@img/sharp-linuxmusl-arm64@0.34.5": optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + "@img/sharp-libvips-linuxmusl-arm64": 1.2.4 optional: true - '@img/sharp-linuxmusl-x64@0.34.5': + "@img/sharp-linuxmusl-x64@0.34.5": optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + "@img/sharp-libvips-linuxmusl-x64": 1.2.4 optional: true - '@img/sharp-wasm32@0.34.5': + "@img/sharp-wasm32@0.34.5": dependencies: - '@emnapi/runtime': 1.11.1 + "@emnapi/runtime": 1.11.1 optional: true - '@img/sharp-win32-arm64@0.34.5': + "@img/sharp-win32-arm64@0.34.5": optional: true - '@img/sharp-win32-ia32@0.34.5': + "@img/sharp-win32-ia32@0.34.5": optional: true - '@img/sharp-win32-x64@0.34.5': + "@img/sharp-win32-x64@0.34.5": optional: true - '@inquirer/ansi@2.0.7': {} + "@inquirer/ansi@2.0.7": {} - '@inquirer/confirm@6.1.1(@types/node@20.19.43)': + "@inquirer/confirm@6.1.1(@types/node@20.19.43)": dependencies: - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@20.19.43) + "@inquirer/core": 11.2.1(@types/node@20.19.43) + "@inquirer/type": 4.0.7(@types/node@20.19.43) optionalDependencies: - '@types/node': 20.19.43 + "@types/node": 20.19.43 - '@inquirer/core@11.2.1(@types/node@20.19.43)': + "@inquirer/core@11.2.1(@types/node@20.19.43)": dependencies: - '@inquirer/ansi': 2.0.7 - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@20.19.43) + "@inquirer/ansi": 2.0.7 + "@inquirer/figures": 2.0.7 + "@inquirer/type": 4.0.7(@types/node@20.19.43) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 mute-stream: 3.0.0 signal-exit: 4.1.0 optionalDependencies: - '@types/node': 20.19.43 + "@types/node": 20.19.43 - '@inquirer/figures@2.0.7': {} + "@inquirer/figures@2.0.7": {} - '@inquirer/type@4.0.7(@types/node@20.19.43)': + "@inquirer/type@4.0.7(@types/node@20.19.43)": optionalDependencies: - '@types/node': 20.19.43 + "@types/node": 20.19.43 - '@jridgewell/gen-mapping@0.3.13': + "@jridgewell/gen-mapping@0.3.13": dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 + "@jridgewell/sourcemap-codec": 1.5.5 + "@jridgewell/trace-mapping": 0.3.31 - '@jridgewell/remapping@2.3.5': + "@jridgewell/remapping@2.3.5": dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 + "@jridgewell/gen-mapping": 0.3.13 + "@jridgewell/trace-mapping": 0.3.31 - '@jridgewell/resolve-uri@3.1.2': {} + "@jridgewell/resolve-uri@3.1.2": {} - '@jridgewell/sourcemap-codec@1.5.5': {} + "@jridgewell/sourcemap-codec@1.5.5": {} - '@jridgewell/trace-mapping@0.3.31': + "@jridgewell/trace-mapping@0.3.31": dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 + "@jridgewell/resolve-uri": 3.1.2 + "@jridgewell/sourcemap-codec": 1.5.5 - '@jridgewell/trace-mapping@0.3.9': + "@jridgewell/trace-mapping@0.3.9": dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 + "@jridgewell/resolve-uri": 3.1.2 + "@jridgewell/sourcemap-codec": 1.5.5 - '@lit-labs/ssr-dom-shim@1.6.0': {} + "@lit-labs/ssr-dom-shim@1.6.0": {} - '@lit/reactive-element@2.1.2': + "@lit/reactive-element@2.1.2": dependencies: - '@lit-labs/ssr-dom-shim': 1.6.0 + "@lit-labs/ssr-dom-shim": 1.6.0 - '@mayanfinance/swap-sdk@13.3.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + "@mayanfinance/swap-sdk@13.3.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)": dependencies: - '@mysten/sui': 1.45.2(typescript@5.9.3) - '@noble/hashes': 1.8.0 - '@solana/buffer-layout': 4.0.1 - '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@mysten/sui": 1.45.2(typescript@5.9.3) + "@noble/hashes": 1.8.0 + "@solana/buffer-layout": 4.0.1 + "@solana/web3.js": 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) bs58: 6.0.0 cross-fetch: 3.2.0 ethers: 6.17.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) js-sha3: 0.8.0 transitivePeerDependencies: - - '@gql.tada/svelte-support' - - '@gql.tada/vue-support' + - "@gql.tada/svelte-support" + - "@gql.tada/vue-support" - bufferutil - encoding - typescript - utf-8-validate - '@mayanfinance/swap-sdk@13.3.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': + "@mayanfinance/swap-sdk@13.3.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)": dependencies: - '@mysten/sui': 1.45.2(typescript@5.9.3) - '@noble/hashes': 1.8.0 - '@solana/buffer-layout': 4.0.1 - '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@mysten/sui": 1.45.2(typescript@5.9.3) + "@noble/hashes": 1.8.0 + "@solana/buffer-layout": 4.0.1 + "@solana/web3.js": 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) bs58: 6.0.0 cross-fetch: 3.2.0 ethers: 6.17.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) js-sha3: 0.8.0 transitivePeerDependencies: - - '@gql.tada/svelte-support' - - '@gql.tada/vue-support' + - "@gql.tada/svelte-support" + - "@gql.tada/vue-support" - bufferutil - encoding - typescript - utf-8-validate - '@mdx-js/mdx@3.1.1': + "@mdx-js/mdx@3.1.1": dependencies: - '@types/estree': 1.0.9 - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdx': 2.0.14 + "@types/estree": 1.0.9 + "@types/estree-jsx": 1.0.5 + "@types/hast": 3.0.4 + "@types/mdx": 2.0.14 acorn: 8.17.0 collapse-white-space: 2.1.0 devlop: 1.1.0 @@ -7855,56 +12476,56 @@ snapshots: transitivePeerDependencies: - supports-color - '@metamask/eth-json-rpc-provider@1.0.1': + "@metamask/eth-json-rpc-provider@1.0.1": dependencies: - '@metamask/json-rpc-engine': 7.3.3 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 5.0.2 + "@metamask/json-rpc-engine": 7.3.3 + "@metamask/safe-event-emitter": 3.1.2 + "@metamask/utils": 5.0.2 transitivePeerDependencies: - supports-color - '@metamask/json-rpc-engine@7.3.3': + "@metamask/json-rpc-engine@7.3.3": dependencies: - '@metamask/rpc-errors': 6.4.0 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 8.5.0 + "@metamask/rpc-errors": 6.4.0 + "@metamask/safe-event-emitter": 3.1.2 + "@metamask/utils": 8.5.0 transitivePeerDependencies: - supports-color - '@metamask/json-rpc-engine@8.0.2': + "@metamask/json-rpc-engine@8.0.2": dependencies: - '@metamask/rpc-errors': 6.4.0 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 8.5.0 + "@metamask/rpc-errors": 6.4.0 + "@metamask/safe-event-emitter": 3.1.2 + "@metamask/utils": 8.5.0 transitivePeerDependencies: - supports-color - '@metamask/json-rpc-middleware-stream@7.0.2': + "@metamask/json-rpc-middleware-stream@7.0.2": dependencies: - '@metamask/json-rpc-engine': 8.0.2 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 8.5.0 + "@metamask/json-rpc-engine": 8.0.2 + "@metamask/safe-event-emitter": 3.1.2 + "@metamask/utils": 8.5.0 readable-stream: 3.6.2 transitivePeerDependencies: - supports-color - '@metamask/object-multiplex@2.1.0': + "@metamask/object-multiplex@2.1.0": dependencies: once: 1.4.0 readable-stream: 3.6.2 - '@metamask/onboarding@1.0.1': + "@metamask/onboarding@1.0.1": dependencies: bowser: 2.14.1 - '@metamask/providers@16.1.0': + "@metamask/providers@16.1.0": dependencies: - '@metamask/json-rpc-engine': 8.0.2 - '@metamask/json-rpc-middleware-stream': 7.0.2 - '@metamask/object-multiplex': 2.1.0 - '@metamask/rpc-errors': 6.4.0 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 8.5.0 + "@metamask/json-rpc-engine": 8.0.2 + "@metamask/json-rpc-middleware-stream": 7.0.2 + "@metamask/object-multiplex": 2.1.0 + "@metamask/rpc-errors": 6.4.0 + "@metamask/safe-event-emitter": 3.1.2 + "@metamask/utils": 8.5.0 detect-browser: 5.3.0 extension-port-stream: 3.0.0 fast-deep-equal: 3.1.3 @@ -7914,31 +12535,31 @@ snapshots: transitivePeerDependencies: - supports-color - '@metamask/rpc-errors@6.4.0': + "@metamask/rpc-errors@6.4.0": dependencies: - '@metamask/utils': 9.3.0 + "@metamask/utils": 9.3.0 fast-safe-stringify: 2.1.1 transitivePeerDependencies: - supports-color - '@metamask/rpc-errors@7.0.2': + "@metamask/rpc-errors@7.0.2": dependencies: - '@metamask/utils': 11.11.0 + "@metamask/utils": 11.11.0 fast-safe-stringify: 2.1.1 transitivePeerDependencies: - supports-color - '@metamask/safe-event-emitter@2.0.0': {} + "@metamask/safe-event-emitter@2.0.0": {} - '@metamask/safe-event-emitter@3.1.2': {} + "@metamask/safe-event-emitter@3.1.2": {} - '@metamask/sdk-analytics@0.0.5': + "@metamask/sdk-analytics@0.0.5": dependencies: openapi-fetch: 0.13.8 - '@metamask/sdk-communication-layer@0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + "@metamask/sdk-communication-layer@0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))": dependencies: - '@metamask/sdk-analytics': 0.0.5 + "@metamask/sdk-analytics": 0.0.5 bufferutil: 4.1.0 cross-fetch: 4.1.0 date-fns: 2.30.0 @@ -7952,19 +12573,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@metamask/sdk-install-modal-web@0.32.1': + "@metamask/sdk-install-modal-web@0.32.1": dependencies: - '@paulmillr/qr': 0.2.1 + "@paulmillr/qr": 0.2.1 - '@metamask/sdk@0.33.1(bufferutil@4.1.0)(utf-8-validate@5.0.10)': + "@metamask/sdk@0.33.1(bufferutil@4.1.0)(utf-8-validate@5.0.10)": dependencies: - '@babel/runtime': 7.29.7 - '@metamask/onboarding': 1.0.1 - '@metamask/providers': 16.1.0 - '@metamask/sdk-analytics': 0.0.5 - '@metamask/sdk-communication-layer': 0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@metamask/sdk-install-modal-web': 0.32.1 - '@paulmillr/qr': 0.2.1 + "@babel/runtime": 7.29.7 + "@metamask/onboarding": 1.0.1 + "@metamask/providers": 16.1.0 + "@metamask/sdk-analytics": 0.0.5 + "@metamask/sdk-communication-layer": 0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + "@metamask/sdk-install-modal-web": 0.32.1 + "@paulmillr/qr": 0.2.1 bowser: 2.14.1 cross-fetch: 4.1.0 debug: 4.3.4 @@ -7984,15 +12605,15 @@ snapshots: - supports-color - utf-8-validate - '@metamask/sdk@0.33.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)': + "@metamask/sdk@0.33.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)": dependencies: - '@babel/runtime': 7.29.7 - '@metamask/onboarding': 1.0.1 - '@metamask/providers': 16.1.0 - '@metamask/sdk-analytics': 0.0.5 - '@metamask/sdk-communication-layer': 0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@metamask/sdk-install-modal-web': 0.32.1 - '@paulmillr/qr': 0.2.1 + "@babel/runtime": 7.29.7 + "@metamask/onboarding": 1.0.1 + "@metamask/providers": 16.1.0 + "@metamask/sdk-analytics": 0.0.5 + "@metamask/sdk-communication-layer": 0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + "@metamask/sdk-install-modal-web": 0.32.1 + "@paulmillr/qr": 0.2.1 bowser: 2.14.1 cross-fetch: 4.1.0 debug: 4.3.4 @@ -8012,16 +12633,16 @@ snapshots: - supports-color - utf-8-validate - '@metamask/superstruct@3.3.0': {} + "@metamask/superstruct@3.3.0": {} - '@metamask/utils@11.11.0': + "@metamask/utils@11.11.0": dependencies: - '@ethereumjs/tx': 4.2.0 - '@metamask/superstruct': 3.3.0 - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 - '@types/debug': 4.1.13 - '@types/lodash': 4.17.24 + "@ethereumjs/tx": 4.2.0 + "@metamask/superstruct": 3.3.0 + "@noble/hashes": 1.8.0 + "@scure/base": 1.2.6 + "@types/debug": 4.1.13 + "@types/lodash": 4.17.24 debug: 4.4.3(supports-color@5.5.0) lodash: 4.18.1 pony-cause: 2.1.11 @@ -8030,23 +12651,23 @@ snapshots: transitivePeerDependencies: - supports-color - '@metamask/utils@5.0.2': + "@metamask/utils@5.0.2": dependencies: - '@ethereumjs/tx': 4.2.0 - '@types/debug': 4.1.13 + "@ethereumjs/tx": 4.2.0 + "@types/debug": 4.1.13 debug: 4.4.3(supports-color@5.5.0) semver: 7.8.5 superstruct: 1.0.4 transitivePeerDependencies: - supports-color - '@metamask/utils@8.5.0': + "@metamask/utils@8.5.0": dependencies: - '@ethereumjs/tx': 4.2.0 - '@metamask/superstruct': 3.3.0 - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 - '@types/debug': 4.1.13 + "@ethereumjs/tx": 4.2.0 + "@metamask/superstruct": 3.3.0 + "@noble/hashes": 1.8.0 + "@scure/base": 1.2.6 + "@types/debug": 4.1.13 debug: 4.4.3(supports-color@5.5.0) pony-cause: 2.1.11 semver: 7.8.5 @@ -8054,13 +12675,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@metamask/utils@9.3.0': + "@metamask/utils@9.3.0": dependencies: - '@ethereumjs/tx': 4.2.0 - '@metamask/superstruct': 3.3.0 - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 - '@types/debug': 4.1.13 + "@ethereumjs/tx": 4.2.0 + "@metamask/superstruct": 3.3.0 + "@noble/hashes": 1.8.0 + "@scure/base": 1.2.6 + "@types/debug": 4.1.13 debug: 4.4.3(supports-color@5.5.0) pony-cause: 2.1.11 semver: 7.8.5 @@ -8068,9 +12689,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@modelcontextprotocol/sdk@1.29.0(zod@3.25.76)': + "@modelcontextprotocol/sdk@1.29.0(zod@3.25.76)": dependencies: - '@hono/node-server': 1.19.14(hono@4.12.27) + "@hono/node-server": 1.19.14(hono@4.12.27) ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) content-type: 1.0.5 @@ -8090,740 +12711,800 @@ snapshots: transitivePeerDependencies: - supports-color - '@motionone/animation@10.18.0': + "@motionone/animation@10.18.0": dependencies: - '@motionone/easing': 10.18.0 - '@motionone/types': 10.17.1 - '@motionone/utils': 10.18.0 + "@motionone/easing": 10.18.0 + "@motionone/types": 10.17.1 + "@motionone/utils": 10.18.0 tslib: 2.8.1 - '@motionone/dom@10.12.0': + "@motionone/dom@10.12.0": dependencies: - '@motionone/animation': 10.18.0 - '@motionone/generators': 10.18.0 - '@motionone/types': 10.17.1 - '@motionone/utils': 10.18.0 + "@motionone/animation": 10.18.0 + "@motionone/generators": 10.18.0 + "@motionone/types": 10.17.1 + "@motionone/utils": 10.18.0 hey-listen: 1.0.8 tslib: 2.8.1 - '@motionone/easing@10.18.0': + "@motionone/easing@10.18.0": dependencies: - '@motionone/utils': 10.18.0 + "@motionone/utils": 10.18.0 tslib: 2.8.1 - '@motionone/generators@10.18.0': + "@motionone/generators@10.18.0": dependencies: - '@motionone/types': 10.17.1 - '@motionone/utils': 10.18.0 + "@motionone/types": 10.17.1 + "@motionone/utils": 10.18.0 tslib: 2.8.1 - '@motionone/types@10.17.1': {} + "@motionone/types@10.17.1": {} - '@motionone/utils@10.18.0': + "@motionone/utils@10.18.0": dependencies: - '@motionone/types': 10.17.1 + "@motionone/types": 10.17.1 hey-listen: 1.0.8 tslib: 2.8.1 - '@mswjs/interceptors@0.41.9': + "@mswjs/interceptors@0.41.9": dependencies: - '@open-draft/deferred-promise': 2.2.0 - '@open-draft/logger': 0.3.0 - '@open-draft/until': 2.1.0 + "@open-draft/deferred-promise": 2.2.0 + "@open-draft/logger": 0.3.0 + "@open-draft/until": 2.1.0 is-node-process: 1.2.0 outvariant: 1.4.3 strict-event-emitter: 0.5.1 - '@mysten/bcs@1.9.2': + "@mysten/bcs@1.9.2": dependencies: - '@mysten/utils': 0.2.0 - '@scure/base': 1.2.6 + "@mysten/utils": 0.2.0 + "@scure/base": 1.2.6 - '@mysten/sui@1.45.2(typescript@5.9.3)': + "@mysten/sui@1.45.2(typescript@5.9.3)": dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.14.2) - '@mysten/bcs': 1.9.2 - '@mysten/utils': 0.2.0 - '@noble/curves': 1.9.4 - '@noble/hashes': 1.8.0 - '@protobuf-ts/grpcweb-transport': 2.11.1 - '@protobuf-ts/runtime': 2.11.1 - '@protobuf-ts/runtime-rpc': 2.11.1 - '@scure/base': 1.2.6 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 + "@graphql-typed-document-node/core": 3.2.0(graphql@16.14.2) + "@mysten/bcs": 1.9.2 + "@mysten/utils": 0.2.0 + "@noble/curves": 1.9.4 + "@noble/hashes": 1.8.0 + "@protobuf-ts/grpcweb-transport": 2.11.1 + "@protobuf-ts/runtime": 2.11.1 + "@protobuf-ts/runtime-rpc": 2.11.1 + "@scure/base": 1.2.6 + "@scure/bip32": 1.7.0 + "@scure/bip39": 1.6.0 gql.tada: 1.11.2(graphql@16.14.2)(typescript@5.9.3) graphql: 16.14.2 poseidon-lite: 0.2.1 valibot: 1.4.2(typescript@5.9.3) transitivePeerDependencies: - - '@gql.tada/svelte-support' - - '@gql.tada/vue-support' + - "@gql.tada/svelte-support" + - "@gql.tada/vue-support" - typescript - '@mysten/utils@0.2.0': + "@mysten/utils@0.2.0": dependencies: - '@scure/base': 1.2.6 + "@scure/base": 1.2.6 - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + "@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)": dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.3 + "@emnapi/core": 1.10.0 + "@emnapi/runtime": 1.10.0 + "@tybys/wasm-util": 0.10.3 optional: true - '@next/env@16.2.3': {} + "@next/env@16.2.3": {} - '@next/eslint-plugin-next@16.2.3': + "@next/eslint-plugin-next@16.2.3": dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@16.2.3': + "@next/swc-darwin-arm64@16.2.3": optional: true - '@next/swc-darwin-x64@16.2.3': + "@next/swc-darwin-x64@16.2.3": optional: true - '@next/swc-linux-arm64-gnu@16.2.3': + "@next/swc-linux-arm64-gnu@16.2.3": optional: true - '@next/swc-linux-arm64-musl@16.2.3': + "@next/swc-linux-arm64-musl@16.2.3": optional: true - '@next/swc-linux-x64-gnu@16.2.3': + "@next/swc-linux-x64-gnu@16.2.3": optional: true - '@next/swc-linux-x64-musl@16.2.3': + "@next/swc-linux-x64-musl@16.2.3": optional: true - '@next/swc-win32-arm64-msvc@16.2.3': + "@next/swc-win32-arm64-msvc@16.2.3": optional: true - '@next/swc-win32-x64-msvc@16.2.3': + "@next/swc-win32-x64-msvc@16.2.3": optional: true - '@noble/ciphers@1.2.1': {} + "@noble/ciphers@1.2.1": {} - '@noble/ciphers@1.3.0': {} + "@noble/ciphers@1.3.0": {} - '@noble/curves@1.2.0': + "@noble/curves@1.2.0": dependencies: - '@noble/hashes': 1.3.2 + "@noble/hashes": 1.3.2 - '@noble/curves@1.4.2': + "@noble/curves@1.4.2": dependencies: - '@noble/hashes': 1.4.0 + "@noble/hashes": 1.4.0 - '@noble/curves@1.8.0': + "@noble/curves@1.8.0": dependencies: - '@noble/hashes': 1.7.0 + "@noble/hashes": 1.7.0 - '@noble/curves@1.8.1': + "@noble/curves@1.8.1": dependencies: - '@noble/hashes': 1.7.1 + "@noble/hashes": 1.7.1 - '@noble/curves@1.9.1': + "@noble/curves@1.9.1": dependencies: - '@noble/hashes': 1.8.0 + "@noble/hashes": 1.8.0 - '@noble/curves@1.9.4': + "@noble/curves@1.9.4": dependencies: - '@noble/hashes': 1.8.0 + "@noble/hashes": 1.8.0 - '@noble/curves@1.9.7': + "@noble/curves@1.9.7": dependencies: - '@noble/hashes': 1.8.0 + "@noble/hashes": 1.8.0 - '@noble/hashes@1.3.2': {} + "@noble/hashes@1.3.2": {} - '@noble/hashes@1.4.0': {} + "@noble/hashes@1.4.0": {} - '@noble/hashes@1.7.0': {} + "@noble/hashes@1.7.0": {} - '@noble/hashes@1.7.1': {} + "@noble/hashes@1.7.1": {} - '@noble/hashes@1.8.0': {} + "@noble/hashes@1.8.0": {} - '@nodelib/fs.scandir@2.1.5': + "@nodelib/fs.scandir@2.1.5": dependencies: - '@nodelib/fs.stat': 2.0.5 + "@nodelib/fs.stat": 2.0.5 run-parallel: 1.2.0 - '@nodelib/fs.stat@2.0.5': {} + "@nodelib/fs.stat@2.0.5": {} - '@nodelib/fs.walk@1.2.8': + "@nodelib/fs.walk@1.2.8": dependencies: - '@nodelib/fs.scandir': 2.1.5 + "@nodelib/fs.scandir": 2.1.5 fastq: 1.20.1 - '@nolyfill/is-core-module@1.0.39': {} + "@nolyfill/is-core-module@1.0.39": {} - '@open-draft/deferred-promise@2.2.0': {} + "@open-draft/deferred-promise@2.2.0": {} - '@open-draft/deferred-promise@3.0.0': {} + "@open-draft/deferred-promise@3.0.0": {} - '@open-draft/logger@0.3.0': + "@open-draft/logger@0.3.0": dependencies: is-node-process: 1.2.0 outvariant: 1.4.3 - '@open-draft/until@2.1.0': {} + "@open-draft/until@2.1.0": {} - '@opentelemetry/api-logs@0.219.0': + "@opentelemetry/api-logs@0.219.0": dependencies: - '@opentelemetry/api': 1.9.1 + "@opentelemetry/api": 1.9.1 - '@opentelemetry/api@1.9.1': {} + "@opentelemetry/api@1.9.1": {} - '@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1)': + "@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1)": dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/semantic-conventions': 1.41.1 + "@opentelemetry/api": 1.9.1 + "@opentelemetry/semantic-conventions": 1.41.1 - '@opentelemetry/exporter-logs-otlp-http@0.219.0(@opentelemetry/api@1.9.1)': + "@opentelemetry/exporter-logs-otlp-http@0.219.0(@opentelemetry/api@1.9.1)": dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/api-logs': 0.219.0 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-exporter-base': 0.219.0(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-transformer': 0.219.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-logs': 0.219.0(@opentelemetry/api@1.9.1) + "@opentelemetry/api": 1.9.1 + "@opentelemetry/api-logs": 0.219.0 + "@opentelemetry/core": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/otlp-exporter-base": 0.219.0(@opentelemetry/api@1.9.1) + "@opentelemetry/otlp-transformer": 0.219.0(@opentelemetry/api@1.9.1) + "@opentelemetry/sdk-logs": 0.219.0(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-exporter-base@0.219.0(@opentelemetry/api@1.9.1)': + "@opentelemetry/otlp-exporter-base@0.219.0(@opentelemetry/api@1.9.1)": dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-transformer': 0.219.0(@opentelemetry/api@1.9.1) + "@opentelemetry/api": 1.9.1 + "@opentelemetry/core": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/otlp-transformer": 0.219.0(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-transformer@0.219.0(@opentelemetry/api@1.9.1)': + "@opentelemetry/otlp-transformer@0.219.0(@opentelemetry/api@1.9.1)": dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/api-logs': 0.219.0 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-logs': 0.219.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-metrics': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/api": 1.9.1 + "@opentelemetry/api-logs": 0.219.0 + "@opentelemetry/core": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/resources": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/sdk-logs": 0.219.0(@opentelemetry/api@1.9.1) + "@opentelemetry/sdk-metrics": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/sdk-trace-base": 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/resources@2.8.0(@opentelemetry/api@1.9.1)': + "@opentelemetry/resources@2.8.0(@opentelemetry/api@1.9.1)": dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 + "@opentelemetry/api": 1.9.1 + "@opentelemetry/core": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/semantic-conventions": 1.41.1 - '@opentelemetry/sdk-logs@0.219.0(@opentelemetry/api@1.9.1)': + "@opentelemetry/sdk-logs@0.219.0(@opentelemetry/api@1.9.1)": dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/api-logs': 0.219.0 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 + "@opentelemetry/api": 1.9.1 + "@opentelemetry/api-logs": 0.219.0 + "@opentelemetry/core": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/resources": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/semantic-conventions": 1.41.1 - '@opentelemetry/sdk-metrics@2.8.0(@opentelemetry/api@1.9.1)': + "@opentelemetry/sdk-metrics@2.8.0(@opentelemetry/api@1.9.1)": dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/api": 1.9.1 + "@opentelemetry/core": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/resources": 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)': + "@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1)": dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.8.0(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 + "@opentelemetry/api": 1.9.1 + "@opentelemetry/core": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/resources": 2.8.0(@opentelemetry/api@1.9.1) + "@opentelemetry/semantic-conventions": 1.41.1 - '@opentelemetry/semantic-conventions@1.41.1': {} + "@opentelemetry/semantic-conventions@1.41.1": {} - '@orama/orama@3.1.18': {} + "@orama/orama@3.1.18": {} - '@paulmillr/qr@0.2.1': {} + "@parcel/watcher-android-arm64@2.5.1": + optional: true + + "@parcel/watcher-darwin-arm64@2.5.1": + optional: true - '@posthog/core@1.30.6': + "@parcel/watcher-darwin-x64@2.5.1": + optional: true + + "@parcel/watcher-freebsd-x64@2.5.1": + optional: true + + "@parcel/watcher-linux-arm-glibc@2.5.1": + optional: true + + "@parcel/watcher-linux-arm-musl@2.5.1": + optional: true + + "@parcel/watcher-linux-arm64-glibc@2.5.1": + optional: true + + "@parcel/watcher-linux-arm64-musl@2.5.1": + optional: true + + "@parcel/watcher-linux-x64-glibc@2.5.1": + optional: true + + "@parcel/watcher-linux-x64-musl@2.5.1": + optional: true + + "@parcel/watcher-win32-arm64@2.5.1": + optional: true + + "@parcel/watcher-win32-ia32@2.5.1": + optional: true + + "@parcel/watcher-win32-x64@2.5.1": + optional: true + + "@parcel/watcher@2.5.1": dependencies: - '@posthog/types': 1.379.3 + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + "@parcel/watcher-android-arm64": 2.5.1 + "@parcel/watcher-darwin-arm64": 2.5.1 + "@parcel/watcher-darwin-x64": 2.5.1 + "@parcel/watcher-freebsd-x64": 2.5.1 + "@parcel/watcher-linux-arm-glibc": 2.5.1 + "@parcel/watcher-linux-arm-musl": 2.5.1 + "@parcel/watcher-linux-arm64-glibc": 2.5.1 + "@parcel/watcher-linux-arm64-musl": 2.5.1 + "@parcel/watcher-linux-x64-glibc": 2.5.1 + "@parcel/watcher-linux-x64-musl": 2.5.1 + "@parcel/watcher-win32-arm64": 2.5.1 + "@parcel/watcher-win32-ia32": 2.5.1 + "@parcel/watcher-win32-x64": 2.5.1 - '@posthog/types@1.379.3': {} + "@paulmillr/qr@0.2.1": {} - '@protobuf-ts/grpcweb-transport@2.11.1': + "@posthog/core@1.30.6": dependencies: - '@protobuf-ts/runtime': 2.11.1 - '@protobuf-ts/runtime-rpc': 2.11.1 + "@posthog/types": 1.379.3 + + "@posthog/types@1.379.3": {} - '@protobuf-ts/runtime-rpc@2.11.1': + "@protobuf-ts/grpcweb-transport@2.11.1": dependencies: - '@protobuf-ts/runtime': 2.11.1 + "@protobuf-ts/runtime": 2.11.1 + "@protobuf-ts/runtime-rpc": 2.11.1 - '@protobuf-ts/runtime@2.11.1': {} + "@protobuf-ts/runtime-rpc@2.11.1": + dependencies: + "@protobuf-ts/runtime": 2.11.1 + + "@protobuf-ts/runtime@2.11.1": {} - '@radix-ui/number@1.1.2': {} + "@radix-ui/number@1.1.2": {} - '@radix-ui/primitive@1.1.4': {} + "@radix-ui/primitive@1.1.4": {} - '@radix-ui/react-accordion@1.2.15(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-accordion@1.2.15(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-collapsible': 1.1.15(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-collection': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-direction': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-collapsible": 1.1.15(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-collection": 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-direction": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-arrow@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-arrow@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-checkbox@1.3.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-previous': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-size': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-checkbox@1.3.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-presence": 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-previous": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-size": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-collapsible@1.1.15(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-collapsible@1.1.15(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-presence": 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-layout-effect": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-collection@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-collection@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-slot': 1.3.0(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-slot": 1.3.0(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-compose-refs@1.1.3(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-compose-refs@1.1.3(@types/react@19.1.2)(react@19.2.2)": dependencies: react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-context@1.1.4(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-context@1.1.4(@types/react@19.1.2)(react@19.2.2)": dependencies: react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 - - '@radix-ui/react-dialog@1.1.18(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-dismissable-layer': 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-focus-scope': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-slot': 1.3.0(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@types/react": 19.1.2 + + "@radix-ui/react-dialog@1.1.18(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-dismissable-layer": 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-focus-guards": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-focus-scope": 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-portal": 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-presence": 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-slot": 1.3.0(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) aria-hidden: 1.2.6 react: 19.2.2 react-dom: 19.2.2(react@19.2.2) react-remove-scroll: 2.7.2(@types/react@19.1.2)(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-direction@1.1.2(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-direction@1.1.2(@types/react@19.1.2)(react@19.2.2)": dependencies: react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-dismissable-layer@1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-dismissable-layer@1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-effect-event': 0.0.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-callback-ref": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-effect-event": 0.0.3(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-dropdown-menu@2.1.19(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-menu': 2.1.19(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-dropdown-menu@2.1.19(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-menu": 2.1.19(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-focus-guards@1.1.4(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-focus-guards@1.1.4(@types/react@19.1.2)(react@19.2.2)": dependencies: react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-focus-scope@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-focus-scope@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-callback-ref": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-id@1.1.2(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-id@1.1.2(@types/react@19.1.2)(react@19.2.2)": dependencies: - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-layout-effect": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-label@2.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-label@2.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-menu@2.1.19(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-collection': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-direction': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-dismissable-layer': 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-focus-scope': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-popper': 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-roving-focus': 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-slot': 1.3.0(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-menu@2.1.19(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-collection": 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-direction": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-dismissable-layer": 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-focus-guards": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-focus-scope": 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-popper": 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-portal": 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-presence": 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-roving-focus": 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-slot": 1.3.0(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-callback-ref": 1.1.2(@types/react@19.1.2)(react@19.2.2) aria-hidden: 1.2.6 react: 19.2.2 react-dom: 19.2.2(react@19.2.2) react-remove-scroll: 2.7.2(@types/react@19.1.2)(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-popover@1.1.18(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-dismissable-layer': 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-focus-scope': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-popper': 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-slot': 1.3.0(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-popover@1.1.18(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-dismissable-layer": 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-focus-guards": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-focus-scope": 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-popper": 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-portal": 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-presence": 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-slot": 1.3.0(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) aria-hidden: 1.2.6 react: 19.2.2 react-dom: 19.2.2(react@19.2.2) react-remove-scroll: 2.7.2(@types/react@19.1.2)(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-popper@1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@floating-ui/react-dom': 2.1.8(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-arrow': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-rect': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-size': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/rect': 1.1.2 + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-popper@1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@floating-ui/react-dom": 2.1.8(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-arrow": 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-callback-ref": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-layout-effect": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-rect": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-size": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/rect": 1.1.2 react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-portal@1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-portal@1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-layout-effect": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-presence@1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-presence@1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-layout-effect": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-primitive@2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-primitive@2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/react-slot': 1.3.0(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-slot": 1.3.0(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-roving-focus@1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-collection': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-direction': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-roving-focus@1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-collection": 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-direction": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-callback-ref": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-select@2.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/number': 1.1.2 - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-collection': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-direction': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-dismissable-layer': 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-focus-scope': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-popper': 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-slot': 1.3.0(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-previous': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-visually-hidden': 1.2.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-select@2.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/number": 1.1.2 + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-collection": 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-direction": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-dismissable-layer": 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-focus-guards": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-focus-scope": 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-popper": 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-portal": 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-presence": 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-slot": 1.3.0(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-callback-ref": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-layout-effect": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-previous": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-visually-hidden": 1.2.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) aria-hidden: 1.2.6 react: 19.2.2 react-dom: 19.2.2(react@19.2.2) react-remove-scroll: 2.7.2(@types/react@19.1.2)(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-separator@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-separator@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-slot@1.3.0(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-slot@1.3.0(@types/react@19.1.2)(react@19.2.2)": dependencies: - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-switch@1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-switch@1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-previous': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-size': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-previous": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-size": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-tabs@1.1.16(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-direction': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-roving-focus': 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-tabs@1.1.16(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-direction": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-presence": 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-roving-focus": 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-toggle-group@1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-direction': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-roving-focus': 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-toggle': 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-toggle-group@1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-direction": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-roving-focus": 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-toggle": 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-toggle@1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-toggle@1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) - - '@radix-ui/react-tooltip@1.2.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': - dependencies: - '@radix-ui/primitive': 1.1.4 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-context': 1.1.4(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-dismissable-layer': 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-id': 1.1.2(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-popper': 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) - '@radix-ui/react-slot': 1.3.0(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-visually-hidden': 1.2.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) + + "@radix-ui/react-tooltip@1.2.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": + dependencies: + "@radix-ui/primitive": 1.1.4 + "@radix-ui/react-compose-refs": 1.1.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-context": 1.1.4(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-dismissable-layer": 1.1.14(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-id": 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-popper": 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-portal": 1.1.13(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-presence": 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-slot": 1.3.0(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-controllable-state": 1.2.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-visually-hidden": 1.2.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/react-use-callback-ref@1.1.2(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-use-callback-ref@1.1.2(@types/react@19.1.2)(react@19.2.2)": dependencies: react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-use-controllable-state@1.2.3(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-use-controllable-state@1.2.3(@types/react@19.1.2)(react@19.2.2)": dependencies: - '@radix-ui/react-use-effect-event': 0.0.3(@types/react@19.1.2)(react@19.2.2) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-effect-event": 0.0.3(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-layout-effect": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-use-effect-event@0.0.3(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-use-effect-event@0.0.3(@types/react@19.1.2)(react@19.2.2)": dependencies: - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-layout-effect": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-use-layout-effect@1.1.2(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-use-layout-effect@1.1.2(@types/react@19.1.2)(react@19.2.2)": dependencies: react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-use-previous@1.1.2(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-use-previous@1.1.2(@types/react@19.1.2)(react@19.2.2)": dependencies: react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-use-rect@1.1.2(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-use-rect@1.1.2(@types/react@19.1.2)(react@19.2.2)": dependencies: - '@radix-ui/rect': 1.1.2 + "@radix-ui/rect": 1.1.2 react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-use-size@1.1.2(@types/react@19.1.2)(react@19.2.2)': + "@radix-ui/react-use-size@1.1.2(@types/react@19.1.2)(react@19.2.2)": dependencies: - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.1.2)(react@19.2.2) + "@radix-ui/react-use-layout-effect": 1.1.2(@types/react@19.1.2)(react@19.2.2) react: 19.2.2 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@radix-ui/react-visually-hidden@1.2.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)': + "@radix-ui/react-visually-hidden@1.2.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)": dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) + "@radix-ui/react-primitive": 2.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) react: 19.2.2 react-dom: 19.2.2(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 - '@types/react-dom': 19.1.2(@types/react@19.1.2) + "@types/react": 19.1.2 + "@types/react-dom": 19.1.2(@types/react@19.1.2) - '@radix-ui/rect@1.1.2': {} + "@radix-ui/rect@1.1.2": {} - '@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.22.4)': + "@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.22.4)": dependencies: big.js: 6.2.2 dayjs: 1.11.13 @@ -8834,7 +13515,7 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': + "@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: big.js: 6.2.2 dayjs: 1.11.13 @@ -8845,7 +13526,7 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.22.4)': + "@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.22.4)": dependencies: big.js: 6.2.2 dayjs: 1.11.13 @@ -8856,7 +13537,7 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + "@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: big.js: 6.2.2 dayjs: 1.11.13 @@ -8867,30 +13548,30 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': + "@reown/appkit-controllers@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@walletconnect/universal-provider": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) valtio: 1.13.2(@types/react@19.1.2)(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.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' + - "@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 @@ -8902,30 +13583,30 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + "@reown/appkit-controllers@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@walletconnect/universal-provider": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) valtio: 1.13.2(@types/react@19.1.2)(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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' + - "@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 @@ -8937,31 +13618,31 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-pay@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': + "@reown/appkit-pay@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-ui': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-utils': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-ui": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-utils": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3) lit: 3.3.0 valtio: 1.13.2(@types/react@19.1.2)(react@19.2.2) 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' + - "@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 @@ -8973,31 +13654,31 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-pay@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + "@reown/appkit-pay@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-ui": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-utils": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76) lit: 3.3.0 valtio: 1.13.2(@types/react@19.1.2)(react@19.2.2) 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' + - "@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 @@ -9009,35 +13690,35 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-polyfills@1.7.8': + "@reown/appkit-polyfills@1.7.8": dependencies: buffer: 6.0.3 - '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3)': + "@reown/appkit-scaffold-ui@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-ui': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-utils': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-ui": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-utils": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3) + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) 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' + - "@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 @@ -9050,31 +13731,31 @@ snapshots: - valtio - zod - '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76)': + "@reown/appkit-scaffold-ui@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-ui": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-utils": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76) + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) 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' + - "@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 @@ -9087,30 +13768,30 @@ snapshots: - valtio - zod - '@reown/appkit-ui@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': + "@reown/appkit-ui@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) 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' + - "@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 @@ -9122,30 +13803,30 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-ui@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + "@reown/appkit-ui@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) 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' + - "@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 @@ -9157,33 +13838,33 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3)': + "@reown/appkit-utils@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-polyfills": 1.7.8 + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@walletconnect/logger": 2.1.2 + "@walletconnect/universal-provider": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) valtio: 1.13.2(@types/react@19.1.2)(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.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' + - "@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 @@ -9195,33 +13876,33 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76)': + "@reown/appkit-utils@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-polyfills": 1.7.8 + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@walletconnect/logger": 2.1.2 + "@walletconnect/universal-provider": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) valtio: 1.13.2(@types/react@19.1.2)(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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' + - "@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 @@ -9233,60 +13914,60 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-wallet@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + "@reown/appkit-wallet@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.22.4) - '@reown/appkit-polyfills': 1.7.8 - '@walletconnect/logger': 2.1.2 + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.22.4) + "@reown/appkit-polyfills": 1.7.8 + "@walletconnect/logger": 2.1.2 zod: 3.22.4 transitivePeerDependencies: - bufferutil - typescript - utf-8-validate - '@reown/appkit-wallet@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': + "@reown/appkit-wallet@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)": dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.22.4) - '@reown/appkit-polyfills': 1.7.8 - '@walletconnect/logger': 2.1.2 + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.22.4) + "@reown/appkit-polyfills": 1.7.8 + "@walletconnect/logger": 2.1.2 zod: 3.22.4 transitivePeerDependencies: - bufferutil - typescript - utf-8-validate - '@reown/appkit@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': - dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-pay': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3) - '@reown/appkit-ui': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@reown/appkit-utils': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@walletconnect/types': 2.21.0 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": + dependencies: + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-pay": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-polyfills": 1.7.8 + "@reown/appkit-scaffold-ui": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3) + "@reown/appkit-ui": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@reown/appkit-utils": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@4.4.3) + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@walletconnect/types": 2.21.0 + "@walletconnect/universal-provider": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) bs58: 6.0.0 valtio: 1.13.2(@types/react@19.1.2)(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.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' + - "@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 @@ -9298,38 +13979,38 @@ snapshots: - utf-8-validate - zod - '@reown/appkit@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': - dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-pay': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@walletconnect/types': 2.21.0 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit@1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": + dependencies: + "@reown/appkit-common": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-controllers": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-pay": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-polyfills": 1.7.8 + "@reown/appkit-scaffold-ui": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76) + "@reown/appkit-ui": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@reown/appkit-utils": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@19.1.2)(react@19.2.2))(zod@3.25.76) + "@reown/appkit-wallet": 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@walletconnect/types": 2.21.0 + "@walletconnect/universal-provider": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) bs58: 6.0.0 valtio: 1.13.2(@types/react@19.1.2)(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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' + - "@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 @@ -9341,11 +14022,11 @@ snapshots: - utf-8-validate - zod - '@rtsao/scc@1.1.0': {} + "@rtsao/scc@1.1.0": {} - '@safe-global/safe-apps-provider@0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': + "@safe-global/safe-apps-provider@0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@safe-global/safe-apps-sdk": 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) events: 3.3.0 transitivePeerDependencies: - bufferutil @@ -9353,9 +14034,9 @@ snapshots: - utf-8-validate - zod - '@safe-global/safe-apps-provider@0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + "@safe-global/safe-apps-provider@0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@safe-global/safe-apps-sdk": 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) events: 3.3.0 transitivePeerDependencies: - bufferutil @@ -9363,9 +14044,9 @@ snapshots: - utf-8-validate - zod - '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': + "@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@safe-global/safe-gateway-typescript-sdk': 3.23.1 + "@safe-global/safe-gateway-typescript-sdk": 3.23.1 viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) transitivePeerDependencies: - bufferutil @@ -9373,9 +14054,9 @@ snapshots: - utf-8-validate - zod - '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + "@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: - '@safe-global/safe-gateway-typescript-sdk': 3.23.1 + "@safe-global/safe-gateway-typescript-sdk": 3.23.1 viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) transitivePeerDependencies: - bufferutil @@ -9383,292 +14064,292 @@ snapshots: - utf-8-validate - zod - '@safe-global/safe-gateway-typescript-sdk@3.23.1': {} + "@safe-global/safe-gateway-typescript-sdk@3.23.1": {} - '@scure/base@1.1.9': {} + "@scure/base@1.1.9": {} - '@scure/base@1.2.6': {} + "@scure/base@1.2.6": {} - '@scure/bip32@1.4.0': + "@scure/bip32@1.4.0": dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.9 + "@noble/curves": 1.4.2 + "@noble/hashes": 1.4.0 + "@scure/base": 1.1.9 - '@scure/bip32@1.6.2': + "@scure/bip32@1.6.2": dependencies: - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@scure/base': 1.2.6 + "@noble/curves": 1.8.1 + "@noble/hashes": 1.7.1 + "@scure/base": 1.2.6 - '@scure/bip32@1.7.0': + "@scure/bip32@1.7.0": dependencies: - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 + "@noble/curves": 1.9.1 + "@noble/hashes": 1.8.0 + "@scure/base": 1.2.6 - '@scure/bip39@1.3.0': + "@scure/bip39@1.3.0": dependencies: - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.9 + "@noble/hashes": 1.4.0 + "@scure/base": 1.1.9 - '@scure/bip39@1.5.4': + "@scure/bip39@1.5.4": dependencies: - '@noble/hashes': 1.7.1 - '@scure/base': 1.2.6 + "@noble/hashes": 1.7.1 + "@scure/base": 1.2.6 - '@scure/bip39@1.6.0': + "@scure/bip39@1.6.0": dependencies: - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 + "@noble/hashes": 1.8.0 + "@scure/base": 1.2.6 - '@shikijs/core@1.29.2': + "@shikijs/core@1.29.2": dependencies: - '@shikijs/engine-javascript': 1.29.2 - '@shikijs/engine-oniguruma': 1.29.2 - '@shikijs/types': 1.29.2 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + "@shikijs/engine-javascript": 1.29.2 + "@shikijs/engine-oniguruma": 1.29.2 + "@shikijs/types": 1.29.2 + "@shikijs/vscode-textmate": 10.0.2 + "@types/hast": 3.0.4 hast-util-to-html: 9.0.5 - '@shikijs/core@4.3.0': + "@shikijs/core@4.3.0": dependencies: - '@shikijs/primitive': 4.3.0 - '@shikijs/types': 4.3.0 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + "@shikijs/primitive": 4.3.0 + "@shikijs/types": 4.3.0 + "@shikijs/vscode-textmate": 10.0.2 + "@types/hast": 3.0.4 hast-util-to-html: 9.0.5 - '@shikijs/engine-javascript@1.29.2': + "@shikijs/engine-javascript@1.29.2": dependencies: - '@shikijs/types': 1.29.2 - '@shikijs/vscode-textmate': 10.0.2 + "@shikijs/types": 1.29.2 + "@shikijs/vscode-textmate": 10.0.2 oniguruma-to-es: 2.3.0 - '@shikijs/engine-javascript@4.3.0': + "@shikijs/engine-javascript@4.3.0": dependencies: - '@shikijs/types': 4.3.0 - '@shikijs/vscode-textmate': 10.0.2 + "@shikijs/types": 4.3.0 + "@shikijs/vscode-textmate": 10.0.2 oniguruma-to-es: 4.3.6 - '@shikijs/engine-oniguruma@1.29.2': + "@shikijs/engine-oniguruma@1.29.2": dependencies: - '@shikijs/types': 1.29.2 - '@shikijs/vscode-textmate': 10.0.2 + "@shikijs/types": 1.29.2 + "@shikijs/vscode-textmate": 10.0.2 - '@shikijs/engine-oniguruma@4.3.0': + "@shikijs/engine-oniguruma@4.3.0": dependencies: - '@shikijs/types': 4.3.0 - '@shikijs/vscode-textmate': 10.0.2 + "@shikijs/types": 4.3.0 + "@shikijs/vscode-textmate": 10.0.2 - '@shikijs/langs@1.29.2': + "@shikijs/langs@1.29.2": dependencies: - '@shikijs/types': 1.29.2 + "@shikijs/types": 1.29.2 - '@shikijs/langs@4.3.0': + "@shikijs/langs@4.3.0": dependencies: - '@shikijs/types': 4.3.0 + "@shikijs/types": 4.3.0 - '@shikijs/primitive@4.3.0': + "@shikijs/primitive@4.3.0": dependencies: - '@shikijs/types': 4.3.0 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + "@shikijs/types": 4.3.0 + "@shikijs/vscode-textmate": 10.0.2 + "@types/hast": 3.0.4 - '@shikijs/themes@1.29.2': + "@shikijs/themes@1.29.2": dependencies: - '@shikijs/types': 1.29.2 + "@shikijs/types": 1.29.2 - '@shikijs/themes@4.3.0': + "@shikijs/themes@4.3.0": dependencies: - '@shikijs/types': 4.3.0 + "@shikijs/types": 4.3.0 - '@shikijs/types@1.29.2': + "@shikijs/types@1.29.2": dependencies: - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + "@shikijs/vscode-textmate": 10.0.2 + "@types/hast": 3.0.4 - '@shikijs/types@4.3.0': + "@shikijs/types@4.3.0": dependencies: - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + "@shikijs/vscode-textmate": 10.0.2 + "@types/hast": 3.0.4 - '@shikijs/vscode-textmate@10.0.2': {} + "@shikijs/vscode-textmate@10.0.2": {} - '@socket.io/component-emitter@3.1.2': {} + "@socket.io/component-emitter@3.1.2": {} - '@solana-program/system@0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6))': + "@solana-program/system@0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6))": dependencies: - '@solana/kit': 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@solana/kit": 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@solana-program/token@0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6))': + "@solana-program/token@0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6))": dependencies: - '@solana/kit': 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@solana/kit": 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@solana/accounts@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/addresses@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/assertions@5.5.1(typescript@5.9.3)': + "@solana/assertions@5.5.1(typescript@5.9.3)": dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) + "@solana/errors": 5.5.1(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 - '@solana/buffer-layout@4.0.1': + "@solana/buffer-layout@4.0.1": dependencies: buffer: 6.0.3 - '@solana/codecs-core@2.3.0(typescript@5.9.3)': + "@solana/codecs-core@2.3.0(typescript@5.9.3)": dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) + "@solana/errors": 2.3.0(typescript@5.9.3) typescript: 5.9.3 - '@solana/codecs-core@5.5.1(typescript@5.9.3)': + "@solana/codecs-core@5.5.1(typescript@5.9.3)": dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) + "@solana/errors": 5.5.1(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 - '@solana/codecs-data-structures@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/codecs-numbers@2.3.0(typescript@5.9.3)': + "@solana/codecs-numbers@2.3.0(typescript@5.9.3)": dependencies: - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) + "@solana/codecs-core": 2.3.0(typescript@5.9.3) + "@solana/errors": 2.3.0(typescript@5.9.3) typescript: 5.9.3 - '@solana/codecs-numbers@5.5.1(typescript@5.9.3)': + "@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) + "@solana/codecs-core": 5.5.1(typescript@5.9.3) + "@solana/errors": 5.5.1(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 - '@solana/codecs-strings@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/codecs@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/errors@2.3.0(typescript@5.9.3)': + "@solana/errors@2.3.0(typescript@5.9.3)": dependencies: chalk: 5.6.2 commander: 14.0.3 typescript: 5.9.3 - '@solana/errors@5.5.1(typescript@5.9.3)': + "@solana/errors@5.5.1(typescript@5.9.3)": dependencies: chalk: 5.6.2 commander: 14.0.2 optionalDependencies: typescript: 5.9.3 - '@solana/fast-stable-stringify@5.5.1(typescript@5.9.3)': + "@solana/fast-stable-stringify@5.5.1(typescript@5.9.3)": optionalDependencies: typescript: 5.9.3 - '@solana/functional@5.5.1(typescript@5.9.3)': + "@solana/functional@5.5.1(typescript@5.9.3)": optionalDependencies: typescript: 5.9.3 - '@solana/instruction-plans@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/instructions@5.5.1(typescript@5.9.3)': + "@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) + "@solana/codecs-core": 5.5.1(typescript@5.9.3) + "@solana/errors": 5.5.1(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 - '@solana/keys@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': - 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/transaction-messages': 5.5.1(typescript@5.9.3) - '@solana/transactions': 5.5.1(typescript@5.9.3) + "@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)": + 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@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: @@ -9676,30 +14357,30 @@ snapshots: - fastestsmallesttextencoderdecoder - utf-8-validate - '@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': - 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@solana/transaction-messages': 5.5.1(typescript@5.9.3) - '@solana/transactions': 5.5.1(typescript@5.9.3) + "@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)": + 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@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: @@ -9707,107 +14388,107 @@ snapshots: - fastestsmallesttextencoderdecoder - utf-8-validate - '@solana/nominal-types@5.5.1(typescript@5.9.3)': + "@solana/nominal-types@5.5.1(typescript@5.9.3)": optionalDependencies: typescript: 5.9.3 - '@solana/offchain-messages@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/options@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/plugin-core@5.5.1(typescript@5.9.3)': + "@solana/plugin-core@5.5.1(typescript@5.9.3)": optionalDependencies: typescript: 5.9.3 - '@solana/programs@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/promises@5.5.1(typescript@5.9.3)': + "@solana/promises@5.5.1(typescript@5.9.3)": optionalDependencies: typescript: 5.9.3 - '@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) + "@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 - '@solana/rpc-parsed-types@5.5.1(typescript@5.9.3)': + "@solana/rpc-parsed-types@5.5.1(typescript@5.9.3)": optionalDependencies: typescript: 5.9.3 - '@solana/rpc-spec-types@5.5.1(typescript@5.9.3)': + "@solana/rpc-spec-types@5.5.1(typescript@5.9.3)": optionalDependencies: typescript: 5.9.3 - '@solana/rpc-spec@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/rpc-subscriptions-api@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/rpc-subscriptions-channel-websocket@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + "@solana/rpc-subscriptions-channel-websocket@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)": 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) + "@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.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) optionalDependencies: typescript: 5.9.3 @@ -9815,12 +14496,12 @@ snapshots: - bufferutil - utf-8-validate - '@solana/rpc-subscriptions-channel-websocket@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': + "@solana/rpc-subscriptions-channel-websocket@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)": 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) + "@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.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: typescript: 5.9.3 @@ -9828,28 +14509,28 @@ snapshots: - bufferutil - utf-8-validate - '@solana/rpc-subscriptions-spec@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/rpc-subscriptions@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': - 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@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) + "@solana/rpc-subscriptions@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)": + 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@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: @@ -9857,19 +14538,19 @@ snapshots: - fastestsmallesttextencoderdecoder - utf-8-validate - '@solana/rpc-subscriptions@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': - 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@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) + "@solana/rpc-subscriptions@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)": + 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@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: @@ -9877,101 +14558,101 @@ snapshots: - fastestsmallesttextencoderdecoder - utf-8-validate - '@solana/rpc-transformers@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/rpc-transport-http@5.5.1(typescript@5.9.3)': + "@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) + "@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.28.0 optionalDependencies: typescript: 5.9.3 - '@solana/rpc-types@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@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) + "@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 - '@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) + "@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 - '@solana/subscribable@5.5.1(typescript@5.9.3)': + "@solana/subscribable@5.5.1(typescript@5.9.3)": dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) + "@solana/errors": 5.5.1(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 - '@solana/sysvars@5.5.1(typescript@5.9.3)': + "@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) + "@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 - '@solana/transaction-confirmation@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': - 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@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) + "@solana/transaction-confirmation@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)": + 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + "@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: @@ -9979,18 +14660,18 @@ snapshots: - fastestsmallesttextencoderdecoder - utf-8-validate - '@solana/transaction-confirmation@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': - 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@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) + "@solana/transaction-confirmation@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)": + 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(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + "@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: @@ -9998,48 +14679,48 @@ snapshots: - fastestsmallesttextencoderdecoder - utf-8-validate - '@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) + "@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 - '@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) + "@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 - '@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + "@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)": dependencies: - '@babel/runtime': 7.29.7 - '@noble/curves': 1.9.7 - '@noble/hashes': 1.8.0 - '@solana/buffer-layout': 4.0.1 - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) + "@babel/runtime": 7.29.7 + "@noble/curves": 1.9.7 + "@noble/hashes": 1.8.0 + "@solana/buffer-layout": 4.0.1 + "@solana/codecs-numbers": 2.3.0(typescript@5.9.3) agentkeepalive: 4.6.0 bn.js: 5.2.4 borsh: 0.7.0 @@ -10056,13 +14737,13 @@ snapshots: - typescript - utf-8-validate - '@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': + "@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)": dependencies: - '@babel/runtime': 7.29.7 - '@noble/curves': 1.9.7 - '@noble/hashes': 1.8.0 - '@solana/buffer-layout': 4.0.1 - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) + "@babel/runtime": 7.29.7 + "@noble/curves": 1.9.7 + "@noble/hashes": 1.8.0 + "@solana/buffer-layout": 4.0.1 + "@solana/codecs-numbers": 2.3.0(typescript@5.9.3) agentkeepalive: 4.6.0 bn.js: 5.2.4 borsh: 0.7.0 @@ -10079,19 +14760,29 @@ snapshots: - typescript - utf-8-validate - '@standard-schema/spec@1.1.0': {} + "@standard-schema/spec@1.1.0": {} - '@swc/helpers@0.5.15': + "@swc/helpers@0.5.15": dependencies: tslib: 2.8.1 - '@swc/helpers@0.5.23': + "@swc/helpers@0.5.23": dependencies: tslib: 2.8.1 - '@tailwindcss/node@4.3.2': + "@tailwindcss/cli@4.3.3": dependencies: - '@jridgewell/remapping': 2.3.5 + "@parcel/watcher": 2.5.1 + "@tailwindcss/node": 4.3.3 + "@tailwindcss/oxide": 4.3.3 + enhanced-resolve: 5.25.1 + mri: 1.2.0 + picocolors: 1.1.1 + tailwindcss: 4.3.3 + + "@tailwindcss/node@4.3.2": + dependencies: + "@jridgewell/remapping": 2.3.5 enhanced-resolve: 5.21.6 jiti: 2.7.0 lightningcss: 1.32.0 @@ -10099,172 +14790,237 @@ snapshots: source-map-js: 1.2.1 tailwindcss: 4.3.2 - '@tailwindcss/oxide-android-arm64@4.3.2': + "@tailwindcss/node@4.3.3": + dependencies: + "@jridgewell/remapping": 2.3.5 + enhanced-resolve: 5.25.1 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.3.3 + + "@tailwindcss/oxide-android-arm64@4.3.2": + optional: true + + "@tailwindcss/oxide-android-arm64@4.3.3": + optional: true + + "@tailwindcss/oxide-darwin-arm64@4.3.2": + optional: true + + "@tailwindcss/oxide-darwin-arm64@4.3.3": + optional: true + + "@tailwindcss/oxide-darwin-x64@4.3.2": + optional: true + + "@tailwindcss/oxide-darwin-x64@4.3.3": + optional: true + + "@tailwindcss/oxide-freebsd-x64@4.3.2": + optional: true + + "@tailwindcss/oxide-freebsd-x64@4.3.3": + optional: true + + "@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2": + optional: true + + "@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3": + optional: true + + "@tailwindcss/oxide-linux-arm64-gnu@4.3.2": + optional: true + + "@tailwindcss/oxide-linux-arm64-gnu@4.3.3": optional: true - '@tailwindcss/oxide-darwin-arm64@4.3.2': + "@tailwindcss/oxide-linux-arm64-musl@4.3.2": optional: true - '@tailwindcss/oxide-darwin-x64@4.3.2': + "@tailwindcss/oxide-linux-arm64-musl@4.3.3": optional: true - '@tailwindcss/oxide-freebsd-x64@4.3.2': + "@tailwindcss/oxide-linux-x64-gnu@4.3.2": optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + "@tailwindcss/oxide-linux-x64-gnu@4.3.3": optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + "@tailwindcss/oxide-linux-x64-musl@4.3.2": optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + "@tailwindcss/oxide-linux-x64-musl@4.3.3": optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + "@tailwindcss/oxide-wasm32-wasi@4.3.2": optional: true - '@tailwindcss/oxide-linux-x64-musl@4.3.2': + "@tailwindcss/oxide-wasm32-wasi@4.3.3": optional: true - '@tailwindcss/oxide-wasm32-wasi@4.3.2': + "@tailwindcss/oxide-win32-arm64-msvc@4.3.2": optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + "@tailwindcss/oxide-win32-arm64-msvc@4.3.3": optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + "@tailwindcss/oxide-win32-x64-msvc@4.3.2": optional: true - '@tailwindcss/oxide@4.3.2': + "@tailwindcss/oxide-win32-x64-msvc@4.3.3": + optional: true + + "@tailwindcss/oxide@4.3.2": + optionalDependencies: + "@tailwindcss/oxide-android-arm64": 4.3.2 + "@tailwindcss/oxide-darwin-arm64": 4.3.2 + "@tailwindcss/oxide-darwin-x64": 4.3.2 + "@tailwindcss/oxide-freebsd-x64": 4.3.2 + "@tailwindcss/oxide-linux-arm-gnueabihf": 4.3.2 + "@tailwindcss/oxide-linux-arm64-gnu": 4.3.2 + "@tailwindcss/oxide-linux-arm64-musl": 4.3.2 + "@tailwindcss/oxide-linux-x64-gnu": 4.3.2 + "@tailwindcss/oxide-linux-x64-musl": 4.3.2 + "@tailwindcss/oxide-wasm32-wasi": 4.3.2 + "@tailwindcss/oxide-win32-arm64-msvc": 4.3.2 + "@tailwindcss/oxide-win32-x64-msvc": 4.3.2 + + "@tailwindcss/oxide@4.3.3": optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.3.2 - '@tailwindcss/oxide-darwin-arm64': 4.3.2 - '@tailwindcss/oxide-darwin-x64': 4.3.2 - '@tailwindcss/oxide-freebsd-x64': 4.3.2 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2 - '@tailwindcss/oxide-linux-arm64-gnu': 4.3.2 - '@tailwindcss/oxide-linux-arm64-musl': 4.3.2 - '@tailwindcss/oxide-linux-x64-gnu': 4.3.2 - '@tailwindcss/oxide-linux-x64-musl': 4.3.2 - '@tailwindcss/oxide-wasm32-wasi': 4.3.2 - '@tailwindcss/oxide-win32-arm64-msvc': 4.3.2 - '@tailwindcss/oxide-win32-x64-msvc': 4.3.2 - - '@tailwindcss/postcss@4.3.2': - dependencies: - '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.3.2 - '@tailwindcss/oxide': 4.3.2 + "@tailwindcss/oxide-android-arm64": 4.3.3 + "@tailwindcss/oxide-darwin-arm64": 4.3.3 + "@tailwindcss/oxide-darwin-x64": 4.3.3 + "@tailwindcss/oxide-freebsd-x64": 4.3.3 + "@tailwindcss/oxide-linux-arm-gnueabihf": 4.3.3 + "@tailwindcss/oxide-linux-arm64-gnu": 4.3.3 + "@tailwindcss/oxide-linux-arm64-musl": 4.3.3 + "@tailwindcss/oxide-linux-x64-gnu": 4.3.3 + "@tailwindcss/oxide-linux-x64-musl": 4.3.3 + "@tailwindcss/oxide-wasm32-wasi": 4.3.3 + "@tailwindcss/oxide-win32-arm64-msvc": 4.3.3 + "@tailwindcss/oxide-win32-x64-msvc": 4.3.3 + + "@tailwindcss/postcss@4.3.2": + dependencies: + "@alloc/quick-lru": 5.2.0 + "@tailwindcss/node": 4.3.2 + "@tailwindcss/oxide": 4.3.2 postcss: 8.5.16 tailwindcss: 4.3.2 - '@tanstack/query-core@5.101.2': {} + "@tanstack/query-core@5.101.2": {} - '@tanstack/react-query@5.101.2(react@19.2.2)': + "@tanstack/react-query@5.101.2(react@19.2.2)": dependencies: - '@tanstack/query-core': 5.101.2 + "@tanstack/query-core": 5.101.2 react: 19.2.2 - '@ts-morph/common@0.19.0': + "@ts-morph/common@0.19.0": dependencies: fast-glob: 3.3.3 minimatch: 7.4.9 mkdirp: 2.1.6 path-browserify: 1.0.1 - '@tsconfig/node10@1.0.12': {} + "@tsconfig/node10@1.0.12": {} - '@tsconfig/node12@1.0.11': {} + "@tsconfig/node12@1.0.11": {} - '@tsconfig/node14@1.0.3': {} + "@tsconfig/node14@1.0.3": {} - '@tsconfig/node16@1.0.4': {} + "@tsconfig/node16@1.0.4": {} - '@tybys/wasm-util@0.10.3': + "@tybys/wasm-util@0.10.3": dependencies: tslib: 2.8.1 optional: true - '@types/connect@3.4.38': + "@types/connect@3.4.38": dependencies: - '@types/node': 20.19.43 + "@types/node": 20.19.43 - '@types/debug@4.1.13': + "@types/debug@4.1.13": dependencies: - '@types/ms': 2.1.0 + "@types/ms": 2.1.0 - '@types/estree-jsx@1.0.5': + "@types/estree-jsx@1.0.5": dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 - '@types/estree@1.0.9': {} + "@types/estree@1.0.9": {} - '@types/hast@3.0.4': + "@types/hast@3.0.4": dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 - '@types/json-schema@7.0.15': {} + "@types/json-schema@7.0.15": {} - '@types/json5@0.0.29': {} + "@types/json5@0.0.29": {} - '@types/lodash@4.17.24': {} + "@types/lodash@4.17.24": {} - '@types/mdast@4.0.4': + "@types/mdast@4.0.4": dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 - '@types/mdx@2.0.14': {} + "@types/mdx@2.0.14": {} - '@types/ms@2.1.0': {} + "@types/ms@2.1.0": {} - '@types/node@12.20.55': {} + "@types/node@12.20.55": {} - '@types/node@20.19.43': + "@types/node@20.19.43": dependencies: undici-types: 6.21.0 - '@types/node@22.7.5': + "@types/node@22.7.5": dependencies: undici-types: 6.19.8 - '@types/react-dom@19.1.2(@types/react@19.1.2)': + "@types/react-dom@19.1.2(@types/react@19.1.2)": dependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 - '@types/react@19.1.2': + "@types/react-test-renderer@19.1.0": + dependencies: + "@types/react": 19.1.2 + + "@types/react@19.1.2": dependencies: csstype: 3.2.3 - '@types/set-cookie-parser@2.4.10': + "@types/set-cookie-parser@2.4.10": dependencies: - '@types/node': 20.19.43 + "@types/node": 20.19.43 - '@types/statuses@2.0.6': {} + "@types/statuses@2.0.6": {} - '@types/trusted-types@2.0.7': {} + "@types/trusted-types@2.0.7": {} - '@types/unist@2.0.11': {} + "@types/unist@2.0.11": {} - '@types/unist@3.0.3': {} + "@types/unist@3.0.3": {} - '@types/uuid@10.0.0': {} + "@types/uuid@10.0.0": {} - '@types/ws@7.4.7': + "@types/ws@7.4.7": dependencies: - '@types/node': 20.19.43 + "@types/node": 20.19.43 - '@types/ws@8.18.1': + "@types/ws@8.18.1": dependencies: - '@types/node': 20.19.43 + "@types/node": 20.19.43 - '@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': + "@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)": dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.62.1 - '@typescript-eslint/type-utils': 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) - '@typescript-eslint/utils': 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.62.1 + "@eslint-community/regexpp": 4.12.2 + "@typescript-eslint/parser": 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + "@typescript-eslint/scope-manager": 8.62.1 + "@typescript-eslint/type-utils": 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + "@typescript-eslint/utils": 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + "@typescript-eslint/visitor-keys": 8.62.1 eslint: 9.39.4(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 @@ -10273,41 +15029,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': + "@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)": dependencies: - '@typescript-eslint/scope-manager': 8.62.1 - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/typescript-estree': 8.62.1(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.62.1 + "@typescript-eslint/scope-manager": 8.62.1 + "@typescript-eslint/types": 8.62.1 + "@typescript-eslint/typescript-estree": 8.62.1(typescript@5.9.3) + "@typescript-eslint/visitor-keys": 8.62.1 debug: 4.4.3(supports-color@5.5.0) eslint: 9.39.4(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.62.1(typescript@5.9.3)': + "@typescript-eslint/project-service@8.62.1(typescript@5.9.3)": dependencies: - '@typescript-eslint/tsconfig-utils': 8.62.1(typescript@5.9.3) - '@typescript-eslint/types': 8.62.1 + "@typescript-eslint/tsconfig-utils": 8.62.1(typescript@5.9.3) + "@typescript-eslint/types": 8.62.1 debug: 4.4.3(supports-color@5.5.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.62.1': + "@typescript-eslint/scope-manager@8.62.1": dependencies: - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/visitor-keys': 8.62.1 + "@typescript-eslint/types": 8.62.1 + "@typescript-eslint/visitor-keys": 8.62.1 - '@typescript-eslint/tsconfig-utils@8.62.1(typescript@5.9.3)': + "@typescript-eslint/tsconfig-utils@8.62.1(typescript@5.9.3)": dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': + "@typescript-eslint/type-utils@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)": dependencies: - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/typescript-estree': 8.62.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + "@typescript-eslint/types": 8.62.1 + "@typescript-eslint/typescript-estree": 8.62.1(typescript@5.9.3) + "@typescript-eslint/utils": 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) debug: 4.4.3(supports-color@5.5.0) eslint: 9.39.4(jiti@2.7.0) ts-api-utils: 2.5.0(typescript@5.9.3) @@ -10315,14 +15071,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.62.1': {} + "@typescript-eslint/types@8.62.1": {} - '@typescript-eslint/typescript-estree@8.62.1(typescript@5.9.3)': + "@typescript-eslint/typescript-estree@8.62.1(typescript@5.9.3)": dependencies: - '@typescript-eslint/project-service': 8.62.1(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.62.1(typescript@5.9.3) - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/visitor-keys': 8.62.1 + "@typescript-eslint/project-service": 8.62.1(typescript@5.9.3) + "@typescript-eslint/tsconfig-utils": 8.62.1(typescript@5.9.3) + "@typescript-eslint/types": 8.62.1 + "@typescript-eslint/visitor-keys": 8.62.1 debug: 4.4.3(supports-color@5.5.0) minimatch: 10.2.5 semver: 7.8.5 @@ -10332,127 +15088,127 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': + "@typescript-eslint/utils@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)": dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) - '@typescript-eslint/scope-manager': 8.62.1 - '@typescript-eslint/types': 8.62.1 - '@typescript-eslint/typescript-estree': 8.62.1(typescript@5.9.3) + "@eslint-community/eslint-utils": 4.9.1(eslint@9.39.4(jiti@2.7.0)) + "@typescript-eslint/scope-manager": 8.62.1 + "@typescript-eslint/types": 8.62.1 + "@typescript-eslint/typescript-estree": 8.62.1(typescript@5.9.3) eslint: 9.39.4(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.62.1': + "@typescript-eslint/visitor-keys@8.62.1": dependencies: - '@typescript-eslint/types': 8.62.1 + "@typescript-eslint/types": 8.62.1 eslint-visitor-keys: 5.0.1 - '@ungap/structured-clone@1.3.2': {} + "@ungap/structured-clone@1.3.2": {} - '@unrs/resolver-binding-android-arm-eabi@1.12.2': + "@unrs/resolver-binding-android-arm-eabi@1.12.2": optional: true - '@unrs/resolver-binding-android-arm64@1.12.2': + "@unrs/resolver-binding-android-arm64@1.12.2": optional: true - '@unrs/resolver-binding-darwin-arm64@1.12.2': + "@unrs/resolver-binding-darwin-arm64@1.12.2": optional: true - '@unrs/resolver-binding-darwin-x64@1.12.2': + "@unrs/resolver-binding-darwin-x64@1.12.2": optional: true - '@unrs/resolver-binding-freebsd-x64@1.12.2': + "@unrs/resolver-binding-freebsd-x64@1.12.2": optional: true - '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': + "@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2": optional: true - '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': + "@unrs/resolver-binding-linux-arm-musleabihf@1.12.2": optional: true - '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': + "@unrs/resolver-binding-linux-arm64-gnu@1.12.2": optional: true - '@unrs/resolver-binding-linux-arm64-musl@1.12.2': + "@unrs/resolver-binding-linux-arm64-musl@1.12.2": optional: true - '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': + "@unrs/resolver-binding-linux-loong64-gnu@1.12.2": optional: true - '@unrs/resolver-binding-linux-loong64-musl@1.12.2': + "@unrs/resolver-binding-linux-loong64-musl@1.12.2": optional: true - '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': + "@unrs/resolver-binding-linux-ppc64-gnu@1.12.2": optional: true - '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': + "@unrs/resolver-binding-linux-riscv64-gnu@1.12.2": optional: true - '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': + "@unrs/resolver-binding-linux-riscv64-musl@1.12.2": optional: true - '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': + "@unrs/resolver-binding-linux-s390x-gnu@1.12.2": optional: true - '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + "@unrs/resolver-binding-linux-x64-gnu@1.12.2": optional: true - '@unrs/resolver-binding-linux-x64-musl@1.12.2': + "@unrs/resolver-binding-linux-x64-musl@1.12.2": optional: true - '@unrs/resolver-binding-openharmony-arm64@1.12.2': + "@unrs/resolver-binding-openharmony-arm64@1.12.2": optional: true - '@unrs/resolver-binding-wasm32-wasi@1.12.2': + "@unrs/resolver-binding-wasm32-wasi@1.12.2": dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + "@emnapi/core": 1.10.0 + "@emnapi/runtime": 1.10.0 + "@napi-rs/wasm-runtime": 1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': + "@unrs/resolver-binding-win32-arm64-msvc@1.12.2": optional: true - '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': + "@unrs/resolver-binding-win32-ia32-msvc@1.12.2": optional: true - '@unrs/resolver-binding-win32-x64-msvc@1.12.2': + "@unrs/resolver-binding-win32-x64-msvc@1.12.2": optional: true - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(zod@4.4.3))(zod@4.4.3)': - dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(zod@4.4.3) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(zod@4.4.3) - '@gemini-wallet/core': 0.3.2(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)) - '@metamask/sdk': 0.33.1(bufferutil@4.1.0)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - cbw-sdk: '@coinbase/wallet-sdk@3.9.3' + "@wagmi/connectors@6.2.0(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(zod@4.4.3))(zod@4.4.3)": + dependencies: + "@base-org/account": 2.4.0(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(zod@4.4.3) + "@coinbase/wallet-sdk": 4.3.6(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(zod@4.4.3) + "@gemini-wallet/core": 0.3.2(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)) + "@metamask/sdk": 0.33.1(bufferutil@4.1.0)(utf-8-validate@5.0.10) + "@safe-global/safe-apps-provider": 0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@safe-global/safe-apps-sdk": 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@wagmi/core": 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + "@walletconnect/ethereum-provider": 2.21.1(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + cbw-sdk: "@coinbase/wallet-sdk@3.9.3" porto: 0.2.35(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(zod@4.4.3)) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) optionalDependencies: 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' - - '@tanstack/react-query' - - '@types/react' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' + - "@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" + - "@tanstack/react-query" + - "@types/react" + - "@upstash/redis" + - "@vercel/blob" + - "@vercel/functions" + - "@vercel/kv" - aws4fetch - bufferutil - db0 @@ -10473,39 +15229,39 @@ snapshots: - wagmi - zod - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)': - dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(zod@3.25.76) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(zod@3.25.76) - '@gemini-wallet/core': 0.3.2(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) - '@metamask/sdk': 0.33.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - cbw-sdk: '@coinbase/wallet-sdk@3.9.3' + "@wagmi/connectors@6.2.0(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)": + dependencies: + "@base-org/account": 2.4.0(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(zod@3.25.76) + "@coinbase/wallet-sdk": 4.3.6(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(zod@3.25.76) + "@gemini-wallet/core": 0.3.2(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + "@metamask/sdk": 0.33.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + "@safe-global/safe-apps-provider": 0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@safe-global/safe-apps-sdk": 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@wagmi/core": 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + "@walletconnect/ethereum-provider": 2.21.1(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + cbw-sdk: "@coinbase/wallet-sdk@3.9.3" porto: 0.2.35(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) optionalDependencies: 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' - - '@tanstack/react-query' - - '@types/react' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' + - "@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" + - "@tanstack/react-query" + - "@types/react" + - "@upstash/redis" + - "@vercel/blob" + - "@vercel/functions" + - "@vercel/kv" - aws4fetch - bufferutil - db0 @@ -10526,71 +15282,71 @@ snapshots: - wagmi - zod - '@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))': + "@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))": dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@5.9.3) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) zustand: 5.0.0(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)) optionalDependencies: - '@tanstack/query-core': 5.101.2 + "@tanstack/query-core": 5.101.2 typescript: 5.9.3 transitivePeerDependencies: - - '@types/react' + - "@types/react" - immer - react - use-sync-external-store - '@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))': + "@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))": dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@5.9.3) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zustand: 5.0.0(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)) optionalDependencies: - '@tanstack/query-core': 5.101.2 + "@tanstack/query-core": 5.101.2 typescript: 5.9.3 transitivePeerDependencies: - - '@types/react' + - "@types/react" - immer - react - use-sync-external-store - '@walletconnect/core@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': - 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(bufferutil@4.1.0)(utf-8-validate@5.0.10) - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/logger': 2.1.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.21.0 - '@walletconnect/utils': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@walletconnect/window-getters': 1.0.1 + "@walletconnect/core@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": + 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(bufferutil@4.1.0)(utf-8-validate@5.0.10) + "@walletconnect/keyvaluestorage": 1.1.1 + "@walletconnect/logger": 2.1.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.21.0 + "@walletconnect/utils": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/window-getters": 1.0.1 es-toolkit: 1.33.0 events: 3.3.0 uint8arrays: 3.1.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' + - "@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 @@ -10600,41 +15356,41 @@ snapshots: - utf-8-validate - zod - '@walletconnect/core@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/logger': 2.1.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.21.0 - '@walletconnect/utils': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@walletconnect/window-getters': 1.0.1 + "@walletconnect/core@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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(bufferutil@4.1.0)(utf-8-validate@6.0.6) + "@walletconnect/keyvaluestorage": 1.1.1 + "@walletconnect/logger": 2.1.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.21.0 + "@walletconnect/utils": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/window-getters": 1.0.1 es-toolkit: 1.33.0 events: 3.3.0 uint8arrays: 3.1.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' + - "@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 @@ -10644,41 +15400,41 @@ snapshots: - utf-8-validate - zod - '@walletconnect/core@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': - 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(bufferutil@4.1.0)(utf-8-validate@5.0.10) - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/logger': 2.1.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.21.1 - '@walletconnect/utils': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@walletconnect/window-getters': 1.0.1 + "@walletconnect/core@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": + 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(bufferutil@4.1.0)(utf-8-validate@5.0.10) + "@walletconnect/keyvaluestorage": 1.1.1 + "@walletconnect/logger": 2.1.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.21.1 + "@walletconnect/utils": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/window-getters": 1.0.1 es-toolkit: 1.33.0 events: 3.3.0 uint8arrays: 3.1.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' + - "@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 @@ -10688,41 +15444,41 @@ snapshots: - utf-8-validate - zod - '@walletconnect/core@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/logger': 2.1.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.21.1 - '@walletconnect/utils': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@walletconnect/window-getters': 1.0.1 + "@walletconnect/core@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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(bufferutil@4.1.0)(utf-8-validate@6.0.6) + "@walletconnect/keyvaluestorage": 1.1.1 + "@walletconnect/logger": 2.1.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.21.1 + "@walletconnect/utils": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/window-getters": 1.0.1 es-toolkit: 1.33.0 events: 3.3.0 uint8arrays: 3.1.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' + - "@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 @@ -10732,40 +15488,40 @@ snapshots: - utf-8-validate - zod - '@walletconnect/environment@1.0.1': + "@walletconnect/environment@1.0.1": dependencies: tslib: 1.14.1 - '@walletconnect/ethereum-provider@2.21.1(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': - dependencies: - '@reown/appkit': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@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/sign-client': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@walletconnect/types': 2.21.1 - '@walletconnect/universal-provider': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@walletconnect/utils': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/ethereum-provider@2.21.1(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": + dependencies: + "@reown/appkit": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@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/sign-client": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/types": 2.21.1 + "@walletconnect/universal-provider": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/utils": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) 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' + - "@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 @@ -10777,36 +15533,36 @@ snapshots: - utf-8-validate - zod - '@walletconnect/ethereum-provider@2.21.1(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': - dependencies: - '@reown/appkit': 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@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/sign-client': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@walletconnect/types': 2.21.1 - '@walletconnect/universal-provider': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@walletconnect/utils': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/ethereum-provider@2.21.1(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": + dependencies: + "@reown/appkit": 1.7.8(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@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/sign-client": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/types": 2.21.1 + "@walletconnect/universal-provider": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/utils": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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' + - "@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 @@ -10818,136 +15574,136 @@ snapshots: - utf-8-validate - zod - '@walletconnect/events@1.0.1': + "@walletconnect/events@1.0.1": dependencies: keyvaluestorage-interface: 1.0.0 tslib: 1.14.1 - '@walletconnect/heartbeat@1.2.2': + "@walletconnect/heartbeat@1.2.2": dependencies: - '@walletconnect/events': 1.0.1 - '@walletconnect/time': 1.0.2 + "@walletconnect/events": 1.0.1 + "@walletconnect/time": 1.0.2 events: 3.3.0 - '@walletconnect/jsonrpc-http-connection@1.0.8': + "@walletconnect/jsonrpc-http-connection@1.0.8": dependencies: - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/safe-json': 1.0.2 + "@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': + "@walletconnect/jsonrpc-provider@1.0.14": dependencies: - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/safe-json': 1.0.2 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/safe-json": 1.0.2 events: 3.3.0 - '@walletconnect/jsonrpc-types@1.0.4': + "@walletconnect/jsonrpc-types@1.0.4": dependencies: events: 3.3.0 keyvaluestorage-interface: 1.0.0 - '@walletconnect/jsonrpc-utils@1.0.8': + "@walletconnect/jsonrpc-utils@1.0.8": dependencies: - '@walletconnect/environment': 1.0.1 - '@walletconnect/jsonrpc-types': 1.0.4 + "@walletconnect/environment": 1.0.1 + "@walletconnect/jsonrpc-types": 1.0.4 tslib: 1.14.1 - '@walletconnect/jsonrpc-ws-connection@1.0.16(bufferutil@4.1.0)(utf-8-validate@5.0.10)': + "@walletconnect/jsonrpc-ws-connection@1.0.16(bufferutil@4.1.0)(utf-8-validate@5.0.10)": dependencies: - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/safe-json': 1.0.2 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/safe-json": 1.0.2 events: 3.3.0 ws: 7.5.11(bufferutil@4.1.0)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate - '@walletconnect/jsonrpc-ws-connection@1.0.16(bufferutil@4.1.0)(utf-8-validate@6.0.6)': + "@walletconnect/jsonrpc-ws-connection@1.0.16(bufferutil@4.1.0)(utf-8-validate@6.0.6)": dependencies: - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/safe-json': 1.0.2 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/safe-json": 1.0.2 events: 3.3.0 ws: 7.5.11(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - utf-8-validate - '@walletconnect/keyvaluestorage@1.1.1': + "@walletconnect/keyvaluestorage@1.1.1": dependencies: - '@walletconnect/safe-json': 1.0.2 + "@walletconnect/safe-json": 1.0.2 idb-keyval: 6.2.6 unstorage: 1.17.5(idb-keyval@6.2.6) 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' + - "@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@2.1.2': + "@walletconnect/logger@2.1.2": dependencies: - '@walletconnect/safe-json': 1.0.2 + "@walletconnect/safe-json": 1.0.2 pino: 7.11.0 - '@walletconnect/relay-api@1.0.11': + "@walletconnect/relay-api@1.0.11": dependencies: - '@walletconnect/jsonrpc-types': 1.0.4 + "@walletconnect/jsonrpc-types": 1.0.4 - '@walletconnect/relay-auth@1.1.0': + "@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 + "@noble/curves": 1.8.0 + "@noble/hashes": 1.7.0 + "@walletconnect/safe-json": 1.0.2 + "@walletconnect/time": 1.0.2 uint8arrays: 3.1.0 - '@walletconnect/safe-json@1.0.2': + "@walletconnect/safe-json@1.0.2": dependencies: tslib: 1.14.1 - '@walletconnect/sign-client@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': + "@walletconnect/sign-client@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@walletconnect/core': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/logger': 2.1.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.0 - '@walletconnect/utils': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/core": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/events": 1.0.1 + "@walletconnect/heartbeat": 1.2.2 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/logger": 2.1.2 + "@walletconnect/time": 1.0.2 + "@walletconnect/types": 2.21.0 + "@walletconnect/utils": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) 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' + - "@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 @@ -10957,33 +15713,33 @@ snapshots: - utf-8-validate - zod - '@walletconnect/sign-client@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + "@walletconnect/sign-client@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: - '@walletconnect/core': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/logger': 2.1.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.0 - '@walletconnect/utils': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/core": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/events": 1.0.1 + "@walletconnect/heartbeat": 1.2.2 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/logger": 2.1.2 + "@walletconnect/time": 1.0.2 + "@walletconnect/types": 2.21.0 + "@walletconnect/utils": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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' + - "@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 @@ -10993,33 +15749,33 @@ snapshots: - utf-8-validate - zod - '@walletconnect/sign-client@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': + "@walletconnect/sign-client@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": dependencies: - '@walletconnect/core': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/logger': 2.1.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.1 - '@walletconnect/utils': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/core": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/events": 1.0.1 + "@walletconnect/heartbeat": 1.2.2 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/logger": 2.1.2 + "@walletconnect/time": 1.0.2 + "@walletconnect/types": 2.21.1 + "@walletconnect/utils": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) 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' + - "@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 @@ -11029,33 +15785,33 @@ snapshots: - utf-8-validate - zod - '@walletconnect/sign-client@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + "@walletconnect/sign-client@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": dependencies: - '@walletconnect/core': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/logger': 2.1.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.1 - '@walletconnect/utils': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/core": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/events": 1.0.1 + "@walletconnect/heartbeat": 1.2.2 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/logger": 2.1.2 + "@walletconnect/time": 1.0.2 + "@walletconnect/types": 2.21.1 + "@walletconnect/utils": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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' + - "@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 @@ -11065,98 +15821,98 @@ snapshots: - utf-8-validate - zod - '@walletconnect/time@1.0.2': + "@walletconnect/time@1.0.2": dependencies: tslib: 1.14.1 - '@walletconnect/types@2.21.0': + "@walletconnect/types@2.21.0": dependencies: - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/logger': 2.1.2 + "@walletconnect/events": 1.0.1 + "@walletconnect/heartbeat": 1.2.2 + "@walletconnect/jsonrpc-types": 1.0.4 + "@walletconnect/keyvaluestorage": 1.1.1 + "@walletconnect/logger": 2.1.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' + - "@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.21.1': + "@walletconnect/types@2.21.1": dependencies: - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/logger': 2.1.2 + "@walletconnect/events": 1.0.1 + "@walletconnect/heartbeat": 1.2.2 + "@walletconnect/jsonrpc-types": 1.0.4 + "@walletconnect/keyvaluestorage": 1.1.1 + "@walletconnect/logger": 2.1.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' + - "@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.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': - 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': 2.1.2 - '@walletconnect/sign-client': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@walletconnect/types': 2.21.0 - '@walletconnect/utils': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/universal-provider@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": + 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": 2.1.2 + "@walletconnect/sign-client": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/types": 2.21.0 + "@walletconnect/utils": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) es-toolkit: 1.33.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' + - "@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 @@ -11167,36 +15923,36 @@ snapshots: - utf-8-validate - zod - '@walletconnect/universal-provider@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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': 2.1.2 - '@walletconnect/sign-client': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@walletconnect/types': 2.21.0 - '@walletconnect/utils': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/universal-provider@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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": 2.1.2 + "@walletconnect/sign-client": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/types": 2.21.0 + "@walletconnect/utils": 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) es-toolkit: 1.33.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' + - "@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 @@ -11207,36 +15963,36 @@ snapshots: - utf-8-validate - zod - '@walletconnect/universal-provider@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': - 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': 2.1.2 - '@walletconnect/sign-client': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) - '@walletconnect/types': 2.21.1 - '@walletconnect/utils': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/universal-provider@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": + 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": 2.1.2 + "@walletconnect/sign-client": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) + "@walletconnect/types": 2.21.1 + "@walletconnect/utils": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) es-toolkit: 1.33.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' + - "@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 @@ -11247,36 +16003,36 @@ snapshots: - utf-8-validate - zod - '@walletconnect/universal-provider@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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': 2.1.2 - '@walletconnect/sign-client': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@walletconnect/types': 2.21.1 - '@walletconnect/utils': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/universal-provider@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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": 2.1.2 + "@walletconnect/sign-client": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + "@walletconnect/types": 2.21.1 + "@walletconnect/utils": 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) es-toolkit: 1.33.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' + - "@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 @@ -11287,41 +16043,41 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': - dependencies: - '@noble/ciphers': 1.2.1 - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1 - '@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.21.0 - '@walletconnect/window-getters': 1.0.1 - '@walletconnect/window-metadata': 1.0.1 + "@walletconnect/utils@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": + dependencies: + "@noble/ciphers": 1.2.1 + "@noble/curves": 1.8.1 + "@noble/hashes": 1.7.1 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/keyvaluestorage": 1.1.1 + "@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.21.0 + "@walletconnect/window-getters": 1.0.1 + "@walletconnect/window-metadata": 1.0.1 bs58: 6.0.0 detect-browser: 5.3.0 query-string: 7.1.3 uint8arrays: 3.1.0 viem: 2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.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' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' + - "@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 @@ -11331,41 +16087,41 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': - dependencies: - '@noble/ciphers': 1.2.1 - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1 - '@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.21.0 - '@walletconnect/window-getters': 1.0.1 - '@walletconnect/window-metadata': 1.0.1 + "@walletconnect/utils@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": + dependencies: + "@noble/ciphers": 1.2.1 + "@noble/curves": 1.8.1 + "@noble/hashes": 1.7.1 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/keyvaluestorage": 1.1.1 + "@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.21.0 + "@walletconnect/window-getters": 1.0.1 + "@walletconnect/window-metadata": 1.0.1 bs58: 6.0.0 detect-browser: 5.3.0 query-string: 7.1.3 uint8arrays: 3.1.0 viem: 2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' + - "@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 @@ -11375,41 +16131,41 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)': - dependencies: - '@noble/ciphers': 1.2.1 - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1 - '@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.21.1 - '@walletconnect/window-getters': 1.0.1 - '@walletconnect/window-metadata': 1.0.1 + "@walletconnect/utils@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)": + dependencies: + "@noble/ciphers": 1.2.1 + "@noble/curves": 1.8.1 + "@noble/hashes": 1.7.1 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/keyvaluestorage": 1.1.1 + "@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.21.1 + "@walletconnect/window-getters": 1.0.1 + "@walletconnect/window-metadata": 1.0.1 bs58: 6.0.0 detect-browser: 5.3.0 query-string: 7.1.3 uint8arrays: 3.1.0 viem: 2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.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' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' + - "@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 @@ -11419,41 +16175,41 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': - dependencies: - '@noble/ciphers': 1.2.1 - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1 - '@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.21.1 - '@walletconnect/window-getters': 1.0.1 - '@walletconnect/window-metadata': 1.0.1 + "@walletconnect/utils@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)": + dependencies: + "@noble/ciphers": 1.2.1 + "@noble/curves": 1.8.1 + "@noble/hashes": 1.7.1 + "@walletconnect/jsonrpc-utils": 1.0.8 + "@walletconnect/keyvaluestorage": 1.1.1 + "@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.21.1 + "@walletconnect/window-getters": 1.0.1 + "@walletconnect/window-metadata": 1.0.1 bs58: 6.0.0 detect-browser: 5.3.0 query-string: 7.1.3 uint8arrays: 3.1.0 viem: 2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' + - "@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 @@ -11463,13 +16219,13 @@ snapshots: - utf-8-validate - zod - '@walletconnect/window-getters@1.0.1': + "@walletconnect/window-getters@1.0.1": dependencies: tslib: 1.14.1 - '@walletconnect/window-metadata@1.0.1': + "@walletconnect/window-metadata@1.0.1": dependencies: - '@walletconnect/window-getters': 1.0.1 + "@walletconnect/window-getters": 1.0.1 tslib: 1.14.1 abitype@1.0.6(typescript@5.9.3)(zod@3.25.76): @@ -11710,14 +16466,14 @@ snapshots: axobject-query@4.1.0: {} - babel-plugin-styled-components@2.3.0(@babel/core@7.29.7)(styled-components@5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@16.13.1)(react@19.2.2))(supports-color@5.5.0): + babel-plugin-styled-components@2.3.0(@babel/core@7.29.7)(styled-components@5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@19.2.8)(react@19.2.2))(supports-color@5.5.0): dependencies: - '@babel/core': 7.29.7 - '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-module-imports': 7.29.7(supports-color@5.5.0) - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + "@babel/core": 7.29.7 + "@babel/helper-annotate-as-pure": 7.29.7 + "@babel/helper-module-imports": 7.29.7(supports-color@5.5.0) + "@babel/plugin-syntax-jsx": 7.29.7(@babel/core@7.29.7) picomatch: 4.0.4 - styled-components: 5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@16.13.1)(react@19.2.2) + styled-components: 5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@19.2.8)(react@19.2.2) transitivePeerDependencies: - supports-color @@ -11979,10 +16735,10 @@ snapshots: concat-map@0.0.1: {} - connectkit@1.9.2(@babel/core@7.29.7)(@tanstack/react-query@5.101.2(react@19.2.2))(react-dom@19.2.2(react@19.2.2))(react-is@16.13.1)(react@19.2.2)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)): + connectkit@1.9.2(@babel/core@7.29.7)(@tanstack/react-query@5.101.2(react@19.2.2))(react-dom@19.2.2(react@19.2.2))(react-is@19.2.8)(react@19.2.2)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)): dependencies: - '@aave/account': 0.2.0(react-dom@19.2.2(react@19.2.2))(react@19.2.2)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)) - '@tanstack/react-query': 5.101.2(react@19.2.2) + "@aave/account": 0.2.0(react-dom@19.2.2(react@19.2.2))(react@19.2.2)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)) + "@tanstack/react-query": 5.101.2(react@19.2.2) buffer: 6.0.3 detect-browser: 5.3.0 framer-motion: 6.5.1(react-dom@19.2.2(react@19.2.2))(react@19.2.2) @@ -11992,11 +16748,11 @@ snapshots: react-transition-state: 1.1.5(react-dom@19.2.2(react@19.2.2))(react@19.2.2) react-use-measure: 2.1.7(react-dom@19.2.2(react@19.2.2))(react@19.2.2) resize-observer-polyfill: 1.5.1 - styled-components: 5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@16.13.1)(react@19.2.2) + styled-components: 5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@19.2.8)(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) wagmi: 2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76) transitivePeerDependencies: - - '@babel/core' + - "@babel/core" - react-is content-disposition@1.1.0: {} @@ -12132,7 +16888,7 @@ snapshots: date-fns@2.30.0: dependencies: - '@babel/runtime': 7.29.7 + "@babel/runtime": 7.29.7 dateformat@4.6.3: {} @@ -12205,6 +16961,8 @@ snapshots: detect-browser@5.3.0: {} + detect-libc@1.0.3: {} + detect-libc@2.1.2: {} detect-node-es@1.1.0: {} @@ -12231,7 +16989,7 @@ snapshots: dompurify@3.4.11: optionalDependencies: - '@types/trusted-types': 2.0.7 + "@types/trusted-types": 2.0.7 dunder-proto@1.0.1: dependencies: @@ -12248,10 +17006,10 @@ snapshots: eciesjs@0.4.18: dependencies: - '@ecies/ciphers': 0.2.6(@noble/ciphers@1.3.0) - '@noble/ciphers': 1.3.0 - '@noble/curves': 1.9.7 - '@noble/hashes': 1.8.0 + "@ecies/ciphers": 0.2.6(@noble/ciphers@1.3.0) + "@noble/ciphers": 1.3.0 + "@noble/curves": 1.9.7 + "@noble/hashes": 1.8.0 ee-first@1.1.1: {} @@ -12283,7 +17041,7 @@ snapshots: engine.io-client@6.6.6(bufferutil@4.1.0)(utf-8-validate@5.0.10): dependencies: - '@socket.io/component-emitter': 3.1.2 + "@socket.io/component-emitter": 3.1.2 debug: 4.4.3(supports-color@5.5.0) engine.io-parser: 5.2.3 ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) @@ -12295,7 +17053,7 @@ snapshots: engine.io-client@6.6.6(bufferutil@4.1.0)(utf-8-validate@6.0.6): dependencies: - '@socket.io/component-emitter': 3.1.2 + "@socket.io/component-emitter": 3.1.2 debug: 4.4.3(supports-color@5.5.0) engine.io-parser: 5.2.3 ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) @@ -12312,6 +17070,11 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.3 + enhanced-resolve@5.25.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + entities@6.0.1: {} error-ex@1.3.4: @@ -12441,75 +17204,75 @@ snapshots: esast-util-from-estree@2.0.0: dependencies: - '@types/estree-jsx': 1.0.5 + "@types/estree-jsx": 1.0.5 devlop: 1.1.0 estree-util-visit: 2.0.0 unist-util-position-from-estree: 2.0.0 esast-util-from-js@2.0.1: dependencies: - '@types/estree-jsx': 1.0.5 + "@types/estree-jsx": 1.0.5 acorn: 8.17.0 esast-util-from-estree: 2.0.0 vfile-message: 4.0.3 esbuild@0.25.12: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 + "@esbuild/aix-ppc64": 0.25.12 + "@esbuild/android-arm": 0.25.12 + "@esbuild/android-arm64": 0.25.12 + "@esbuild/android-x64": 0.25.12 + "@esbuild/darwin-arm64": 0.25.12 + "@esbuild/darwin-x64": 0.25.12 + "@esbuild/freebsd-arm64": 0.25.12 + "@esbuild/freebsd-x64": 0.25.12 + "@esbuild/linux-arm": 0.25.12 + "@esbuild/linux-arm64": 0.25.12 + "@esbuild/linux-ia32": 0.25.12 + "@esbuild/linux-loong64": 0.25.12 + "@esbuild/linux-mips64el": 0.25.12 + "@esbuild/linux-ppc64": 0.25.12 + "@esbuild/linux-riscv64": 0.25.12 + "@esbuild/linux-s390x": 0.25.12 + "@esbuild/linux-x64": 0.25.12 + "@esbuild/netbsd-arm64": 0.25.12 + "@esbuild/netbsd-x64": 0.25.12 + "@esbuild/openbsd-arm64": 0.25.12 + "@esbuild/openbsd-x64": 0.25.12 + "@esbuild/openharmony-arm64": 0.25.12 + "@esbuild/sunos-x64": 0.25.12 + "@esbuild/win32-arm64": 0.25.12 + "@esbuild/win32-ia32": 0.25.12 + "@esbuild/win32-x64": 0.25.12 esbuild@0.28.1: optionalDependencies: - '@esbuild/aix-ppc64': 0.28.1 - '@esbuild/android-arm': 0.28.1 - '@esbuild/android-arm64': 0.28.1 - '@esbuild/android-x64': 0.28.1 - '@esbuild/darwin-arm64': 0.28.1 - '@esbuild/darwin-x64': 0.28.1 - '@esbuild/freebsd-arm64': 0.28.1 - '@esbuild/freebsd-x64': 0.28.1 - '@esbuild/linux-arm': 0.28.1 - '@esbuild/linux-arm64': 0.28.1 - '@esbuild/linux-ia32': 0.28.1 - '@esbuild/linux-loong64': 0.28.1 - '@esbuild/linux-mips64el': 0.28.1 - '@esbuild/linux-ppc64': 0.28.1 - '@esbuild/linux-riscv64': 0.28.1 - '@esbuild/linux-s390x': 0.28.1 - '@esbuild/linux-x64': 0.28.1 - '@esbuild/netbsd-arm64': 0.28.1 - '@esbuild/netbsd-x64': 0.28.1 - '@esbuild/openbsd-arm64': 0.28.1 - '@esbuild/openbsd-x64': 0.28.1 - '@esbuild/openharmony-arm64': 0.28.1 - '@esbuild/sunos-x64': 0.28.1 - '@esbuild/win32-arm64': 0.28.1 - '@esbuild/win32-ia32': 0.28.1 - '@esbuild/win32-x64': 0.28.1 + "@esbuild/aix-ppc64": 0.28.1 + "@esbuild/android-arm": 0.28.1 + "@esbuild/android-arm64": 0.28.1 + "@esbuild/android-x64": 0.28.1 + "@esbuild/darwin-arm64": 0.28.1 + "@esbuild/darwin-x64": 0.28.1 + "@esbuild/freebsd-arm64": 0.28.1 + "@esbuild/freebsd-x64": 0.28.1 + "@esbuild/linux-arm": 0.28.1 + "@esbuild/linux-arm64": 0.28.1 + "@esbuild/linux-ia32": 0.28.1 + "@esbuild/linux-loong64": 0.28.1 + "@esbuild/linux-mips64el": 0.28.1 + "@esbuild/linux-ppc64": 0.28.1 + "@esbuild/linux-riscv64": 0.28.1 + "@esbuild/linux-s390x": 0.28.1 + "@esbuild/linux-x64": 0.28.1 + "@esbuild/netbsd-arm64": 0.28.1 + "@esbuild/netbsd-x64": 0.28.1 + "@esbuild/openbsd-arm64": 0.28.1 + "@esbuild/openbsd-x64": 0.28.1 + "@esbuild/openharmony-arm64": 0.28.1 + "@esbuild/sunos-x64": 0.28.1 + "@esbuild/win32-arm64": 0.28.1 + "@esbuild/win32-ia32": 0.28.1 + "@esbuild/win32-x64": 0.28.1 escalade@3.2.0: {} @@ -12521,7 +17284,7 @@ snapshots: eslint-config-next@16.2.3(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3): dependencies: - '@next/eslint-plugin-next': 16.2.3 + "@next/eslint-plugin-next": 16.2.3 eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)) @@ -12534,7 +17297,7 @@ snapshots: optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - - '@typescript-eslint/parser' + - "@typescript-eslint/parser" - eslint-import-resolver-webpack - eslint-plugin-import-x - supports-color @@ -12549,7 +17312,7 @@ snapshots: eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)): dependencies: - '@nolyfill/is-core-module': 1.0.39 + "@nolyfill/is-core-module": 1.0.39 debug: 4.4.3(supports-color@5.5.0) eslint: 9.39.4(jiti@2.7.0) get-tsconfig: 4.14.0 @@ -12566,7 +17329,7 @@ snapshots: dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + "@typescript-eslint/parser": 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)) @@ -12575,7 +17338,7 @@ snapshots: eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)): dependencies: - '@rtsao/scc': 1.1.0 + "@rtsao/scc": 1.1.0 array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 @@ -12596,7 +17359,7 @@ snapshots: string.prototype.trimend: 1.0.10 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + "@typescript-eslint/parser": 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -12623,8 +17386,8 @@ snapshots: eslint-plugin-react-hooks@7.1.1(eslint@9.39.4(jiti@2.7.0)): dependencies: - '@babel/core': 7.29.7 - '@babel/parser': 7.29.7 + "@babel/core": 7.29.7 + "@babel/parser": 7.29.7 eslint: 9.39.4(jiti@2.7.0) hermes-parser: 0.25.1 zod: 3.25.76 @@ -12667,18 +17430,18 @@ snapshots: eslint@9.39.4(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.2 - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.5 - '@eslint/js': 9.39.4 - '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.8 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.9 + "@eslint-community/eslint-utils": 4.9.1(eslint@9.39.4(jiti@2.7.0)) + "@eslint-community/regexpp": 4.12.2 + "@eslint/config-array": 0.21.2 + "@eslint/config-helpers": 0.4.2 + "@eslint/core": 0.17.0 + "@eslint/eslintrc": 3.3.5 + "@eslint/js": 9.39.4 + "@eslint/plugin-kit": 0.4.1 + "@humanfs/node": 0.16.8 + "@humanwhocodes/module-importer": 1.0.1 + "@humanwhocodes/retry": 0.4.3 + "@types/estree": 1.0.9 ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 @@ -12726,11 +17489,11 @@ snapshots: estree-util-attach-comments@3.0.0: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 estree-util-build-jsx@3.0.1: dependencies: - '@types/estree-jsx': 1.0.5 + "@types/estree-jsx": 1.0.5 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 estree-walker: 3.0.3 @@ -12739,27 +17502,27 @@ snapshots: estree-util-scope@1.0.0: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 devlop: 1.1.0 estree-util-to-js@2.0.0: dependencies: - '@types/estree-jsx': 1.0.5 + "@types/estree-jsx": 1.0.5 astring: 1.9.0 source-map: 0.7.6 estree-util-value-to-estree@3.5.0: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 estree-util-visit@2.0.0: dependencies: - '@types/estree-jsx': 1.0.5 - '@types/unist': 3.0.3 + "@types/estree-jsx": 1.0.5 + "@types/unist": 3.0.3 estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 esutils@2.0.3: {} @@ -12767,9 +17530,9 @@ snapshots: eth-block-tracker@7.1.0: dependencies: - '@metamask/eth-json-rpc-provider': 1.0.1 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 5.0.2 + "@metamask/eth-json-rpc-provider": 1.0.1 + "@metamask/safe-event-emitter": 3.1.2 + "@metamask/utils": 5.0.2 json-rpc-random-id: 1.0.1 pify: 3.0.0 transitivePeerDependencies: @@ -12777,7 +17540,7 @@ snapshots: eth-json-rpc-filters@6.0.1: dependencies: - '@metamask/safe-event-emitter': 3.1.2 + "@metamask/safe-event-emitter": 3.1.2 async-mutex: 0.2.6 eth-query: 2.1.2 json-rpc-engine: 6.1.0 @@ -12794,17 +17557,17 @@ snapshots: ethereum-cryptography@2.2.1: dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 + "@noble/curves": 1.4.2 + "@noble/hashes": 1.4.0 + "@scure/bip32": 1.4.0 + "@scure/bip39": 1.3.0 ethers@6.17.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): dependencies: - '@adraffy/ens-normalize': 1.11.1 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@types/node': 22.7.5 + "@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(bufferutil@4.1.0)(utf-8-validate@5.0.10) @@ -12814,10 +17577,10 @@ snapshots: ethers@6.17.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): dependencies: - '@adraffy/ens-normalize': 1.11.1 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@types/node': 22.7.5 + "@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(bufferutil@4.1.0)(utf-8-validate@6.0.6) @@ -12909,16 +17672,16 @@ snapshots: fast-glob@3.3.1: dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 + "@nodelib/fs.stat": 2.0.5 + "@nodelib/fs.walk": 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.8 fast-glob@3.3.3: dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 + "@nodelib/fs.stat": 2.0.5 + "@nodelib/fs.walk": 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.8 @@ -13020,7 +17783,7 @@ snapshots: framer-motion@6.5.1(react-dom@19.2.2(react@19.2.2))(react@19.2.2): dependencies: - '@motionone/dom': 10.12.0 + "@motionone/dom": 10.12.0 framesync: 6.0.1 hey-listen: 1.0.8 popmotion: 11.0.3 @@ -13029,7 +17792,7 @@ snapshots: style-value-types: 5.0.0 tslib: 2.8.1 optionalDependencies: - '@emotion/is-prop-valid': 0.8.8 + "@emotion/is-prop-valid": 0.8.8 framesync@6.0.1: dependencies: @@ -13052,7 +17815,7 @@ snapshots: fumadocs-core@16.10.7(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.1.2)(lucide-react@0.487.0(react@19.2.2))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(react-dom@19.2.2(react@19.2.2))(react@19.2.2)(zod@3.25.76): dependencies: - '@orama/orama': 3.1.18 + "@orama/orama": 3.1.18 estree-util-value-to-estree: 3.5.0 github-slugger: 2.0.0 hast-util-to-estree: 3.1.3 @@ -13070,11 +17833,11 @@ snapshots: unist-util-visit: 5.1.0 vfile: 6.0.3 optionalDependencies: - '@mdx-js/mdx': 3.1.1 - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/react': 19.1.2 + "@mdx-js/mdx": 3.1.1 + "@types/estree-jsx": 1.0.5 + "@types/hast": 3.0.4 + "@types/mdast": 4.0.4 + "@types/react": 19.1.2 lucide-react: 0.487.0(react@19.2.2) next: 16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2) react: 19.2.2 @@ -13085,8 +17848,8 @@ snapshots: fumadocs-mdx@13.0.8(fumadocs-core@16.10.7(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.1.2)(lucide-react@0.487.0(react@19.2.2))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(react-dom@19.2.2(react@19.2.2))(react@19.2.2)(zod@3.25.76))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(react@19.2.2): dependencies: - '@mdx-js/mdx': 3.1.1 - '@standard-schema/spec': 1.1.0 + "@mdx-js/mdx": 3.1.1 + "@standard-schema/spec": 1.1.0 chokidar: 4.0.3 esbuild: 0.25.12 estree-util-value-to-estree: 3.5.0 @@ -13188,14 +17951,14 @@ snapshots: gql.tada@1.11.2(graphql@16.14.2)(typescript@5.9.3): dependencies: - '@0no-co/graphql.web': 1.3.2(graphql@16.14.2) - '@0no-co/graphqlsp': 1.17.3(graphql@16.14.2)(typescript@5.9.3) - '@gql.tada/cli-utils': 1.9.2(@0no-co/graphqlsp@1.17.3(graphql@16.14.2)(typescript@5.9.3))(graphql@16.14.2)(typescript@5.9.3) - '@gql.tada/internal': 1.2.1(graphql@16.14.2)(typescript@5.9.3) + "@0no-co/graphql.web": 1.3.2(graphql@16.14.2) + "@0no-co/graphqlsp": 1.17.3(graphql@16.14.2)(typescript@5.9.3) + "@gql.tada/cli-utils": 1.9.2(@0no-co/graphqlsp@1.17.3(graphql@16.14.2)(typescript@5.9.3))(graphql@16.14.2)(typescript@5.9.3) + "@gql.tada/internal": 1.2.1(graphql@16.14.2)(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - - '@gql.tada/svelte-support' - - '@gql.tada/vue-support' + - "@gql.tada/svelte-support" + - "@gql.tada/vue-support" - graphql graceful-fs@4.2.11: {} @@ -13257,7 +18020,7 @@ snapshots: hast-util-from-html@2.0.3: dependencies: - '@types/hast': 3.0.4 + "@types/hast": 3.0.4 devlop: 1.1.0 hast-util-from-parse5: 8.0.3 parse5: 7.3.0 @@ -13266,8 +18029,8 @@ snapshots: hast-util-from-parse5@8.0.3: dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 + "@types/hast": 3.0.4 + "@types/unist": 3.0.3 devlop: 1.1.0 hastscript: 9.0.1 property-information: 7.2.0 @@ -13277,13 +18040,13 @@ snapshots: hast-util-parse-selector@4.0.0: dependencies: - '@types/hast': 3.0.4 + "@types/hast": 3.0.4 hast-util-to-estree@3.1.3: dependencies: - '@types/estree': 1.0.9 - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 + "@types/estree": 1.0.9 + "@types/estree-jsx": 1.0.5 + "@types/hast": 3.0.4 comma-separated-tokens: 2.0.3 devlop: 1.1.0 estree-util-attach-comments: 3.0.0 @@ -13302,8 +18065,8 @@ snapshots: hast-util-to-html@9.0.5: dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 + "@types/hast": 3.0.4 + "@types/unist": 3.0.3 ccount: 2.0.1 comma-separated-tokens: 2.0.3 hast-util-whitespace: 3.0.0 @@ -13316,9 +18079,9 @@ snapshots: hast-util-to-jsx-runtime@2.3.6: dependencies: - '@types/estree': 1.0.9 - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 + "@types/estree": 1.0.9 + "@types/hast": 3.0.4 + "@types/unist": 3.0.3 comma-separated-tokens: 2.0.3 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 @@ -13336,15 +18099,15 @@ snapshots: hast-util-to-string@3.0.1: dependencies: - '@types/hast': 3.0.4 + "@types/hast": 3.0.4 hast-util-whitespace@3.0.0: dependencies: - '@types/hast': 3.0.4 + "@types/hast": 3.0.4 hastscript@9.0.1: dependencies: - '@types/hast': 3.0.4 + "@types/hast": 3.0.4 comma-separated-tokens: 2.0.3 hast-util-parse-selector: 4.0.0 property-information: 7.2.0 @@ -13352,7 +18115,7 @@ snapshots: headers-polyfill@5.0.1: dependencies: - '@types/set-cookie-parser': 2.4.10 + "@types/set-cookie-parser": 2.4.10 set-cookie-parser: 3.1.1 help-me@5.0.0: {} @@ -13647,9 +18410,9 @@ snapshots: jayson@4.3.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): dependencies: - '@types/connect': 3.4.38 - '@types/node': 12.20.55 - '@types/ws': 7.4.7 + "@types/connect": 3.4.38 + "@types/node": 12.20.55 + "@types/ws": 7.4.7 commander: 2.20.3 delay: 5.0.0 es6-promisify: 5.0.0 @@ -13665,9 +18428,9 @@ snapshots: jayson@4.3.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): dependencies: - '@types/connect': 3.4.38 - '@types/node': 12.20.55 - '@types/ws': 7.4.7 + "@types/connect": 3.4.38 + "@types/node": 12.20.55 + "@types/ws": 7.4.7 commander: 2.20.3 delay: 5.0.0 es6-promisify: 5.0.0 @@ -13712,7 +18475,7 @@ snapshots: json-rpc-engine@6.1.0: dependencies: - '@metamask/safe-event-emitter': 2.0.0 + "@metamask/safe-event-emitter": 2.0.0 eth-rpc-errors: 4.0.3 json-rpc-random-id@1.0.1: {} @@ -13826,17 +18589,17 @@ snapshots: lit-element@4.2.2: dependencies: - '@lit-labs/ssr-dom-shim': 1.6.0 - '@lit/reactive-element': 2.1.2 + "@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 + "@types/trusted-types": 2.0.7 lit@3.3.0: dependencies: - '@lit/reactive-element': 2.1.2 + "@lit/reactive-element": 2.1.2 lit-element: 4.2.2 lit-html: 3.3.3 @@ -13875,7 +18638,7 @@ snapshots: magic-string@0.30.21: dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + "@jridgewell/sourcemap-codec": 1.5.5 make-error@1.3.6: {} @@ -13899,15 +18662,15 @@ snapshots: mdast-util-find-and-replace@3.0.2: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 escape-string-regexp: 5.0.0 unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 mdast-util-from-markdown@2.0.3: dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 + "@types/mdast": 4.0.4 + "@types/unist": 3.0.3 decode-named-character-reference: 1.3.0 devlop: 1.1.0 mdast-util-to-string: 4.0.0 @@ -13923,7 +18686,7 @@ snapshots: mdast-util-gfm-autolink-literal@2.0.1: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 ccount: 2.0.1 devlop: 1.1.0 mdast-util-find-and-replace: 3.0.2 @@ -13931,7 +18694,7 @@ snapshots: mdast-util-gfm-footnote@2.1.0: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 devlop: 1.1.0 mdast-util-from-markdown: 2.0.3 mdast-util-to-markdown: 2.1.2 @@ -13941,7 +18704,7 @@ snapshots: mdast-util-gfm-strikethrough@2.0.0: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 mdast-util-from-markdown: 2.0.3 mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: @@ -13949,7 +18712,7 @@ snapshots: mdast-util-gfm-table@2.0.0: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 devlop: 1.1.0 markdown-table: 3.0.4 mdast-util-from-markdown: 2.0.3 @@ -13959,7 +18722,7 @@ snapshots: mdast-util-gfm-task-list-item@2.0.0: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 devlop: 1.1.0 mdast-util-from-markdown: 2.0.3 mdast-util-to-markdown: 2.1.2 @@ -13980,9 +18743,9 @@ snapshots: mdast-util-mdx-expression@2.0.1: dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 + "@types/estree-jsx": 1.0.5 + "@types/hast": 3.0.4 + "@types/mdast": 4.0.4 devlop: 1.1.0 mdast-util-from-markdown: 2.0.3 mdast-util-to-markdown: 2.1.2 @@ -13991,10 +18754,10 @@ snapshots: mdast-util-mdx-jsx@3.2.0: dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 + "@types/estree-jsx": 1.0.5 + "@types/hast": 3.0.4 + "@types/mdast": 4.0.4 + "@types/unist": 3.0.3 ccount: 2.0.1 devlop: 1.1.0 mdast-util-from-markdown: 2.0.3 @@ -14018,9 +18781,9 @@ snapshots: mdast-util-mdxjs-esm@2.0.1: dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 + "@types/estree-jsx": 1.0.5 + "@types/hast": 3.0.4 + "@types/mdast": 4.0.4 devlop: 1.1.0 mdast-util-from-markdown: 2.0.3 mdast-util-to-markdown: 2.1.2 @@ -14029,14 +18792,14 @@ snapshots: mdast-util-phrasing@4.1.0: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 unist-util-is: 6.0.1 mdast-util-to-hast@13.2.1: dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.3.2 + "@types/hast": 3.0.4 + "@types/mdast": 4.0.4 + "@ungap/structured-clone": 1.3.2 devlop: 1.1.0 micromark-util-sanitize-uri: 2.0.1 trim-lines: 3.0.1 @@ -14046,8 +18809,8 @@ snapshots: mdast-util-to-markdown@2.1.2: dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 + "@types/mdast": 4.0.4 + "@types/unist": 3.0.3 longest-streak: 3.1.0 mdast-util-phrasing: 4.1.0 mdast-util-to-string: 4.0.0 @@ -14058,7 +18821,7 @@ snapshots: mdast-util-to-string@4.0.0: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 media-typer@1.1.0: {} @@ -14149,7 +18912,7 @@ snapshots: micromark-extension-mdx-expression@3.0.1: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 devlop: 1.1.0 micromark-factory-mdx-expression: 2.0.3 micromark-factory-space: 2.0.1 @@ -14160,7 +18923,7 @@ snapshots: micromark-extension-mdx-jsx@3.0.2: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 micromark-factory-mdx-expression: 2.0.3 @@ -14177,7 +18940,7 @@ snapshots: micromark-extension-mdxjs-esm@3.0.0: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 micromark-util-character: 2.1.1 @@ -14213,7 +18976,7 @@ snapshots: micromark-factory-mdx-expression@2.0.3: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 devlop: 1.1.0 micromark-factory-space: 2.0.1 micromark-util-character: 2.1.1 @@ -14277,8 +19040,8 @@ snapshots: micromark-util-events-to-acorn@2.0.3: dependencies: - '@types/estree': 1.0.9 - '@types/unist': 3.0.3 + "@types/estree": 1.0.9 + "@types/unist": 3.0.3 devlop: 1.1.0 estree-util-visit: 2.0.0 micromark-util-symbol: 2.0.1 @@ -14314,7 +19077,7 @@ snapshots: micromark@4.0.2: dependencies: - '@types/debug': 4.1.13 + "@types/debug": 4.1.13 debug: 4.4.3(supports-color@5.5.0) decode-named-character-reference: 1.3.0 devlop: 1.1.0 @@ -14384,16 +19147,18 @@ snapshots: mkdirp@2.1.6: {} + mri@1.2.0: {} + ms@2.1.2: {} ms@2.1.3: {} msw@2.14.6(@types/node@20.19.43)(typescript@5.9.3): dependencies: - '@inquirer/confirm': 6.1.1(@types/node@20.19.43) - '@mswjs/interceptors': 0.41.9 - '@open-draft/deferred-promise': 3.0.0 - '@types/statuses': 2.0.6 + "@inquirer/confirm": 6.1.1(@types/node@20.19.43) + "@mswjs/interceptors": 0.41.9 + "@open-draft/deferred-promise": 3.0.0 + "@types/statuses": 2.0.6 cookie: 1.1.1 graphql: 16.14.2 headers-polyfill: 5.0.1 @@ -14411,7 +19176,7 @@ snapshots: optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - - '@types/node' + - "@types/node" multiformats@9.9.0: {} @@ -14432,8 +19197,8 @@ snapshots: next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2): dependencies: - '@next/env': 16.2.3 - '@swc/helpers': 0.5.15 + "@next/env": 16.2.3 + "@swc/helpers": 0.5.15 baseline-browser-mapping: 2.10.40 caniuse-lite: 1.0.30001800 postcss: 8.4.31 @@ -14441,22 +19206,24 @@ snapshots: react-dom: 19.2.2(react@19.2.2) styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.2) optionalDependencies: - '@next/swc-darwin-arm64': 16.2.3 - '@next/swc-darwin-x64': 16.2.3 - '@next/swc-linux-arm64-gnu': 16.2.3 - '@next/swc-linux-arm64-musl': 16.2.3 - '@next/swc-linux-x64-gnu': 16.2.3 - '@next/swc-linux-x64-musl': 16.2.3 - '@next/swc-win32-arm64-msvc': 16.2.3 - '@next/swc-win32-x64-msvc': 16.2.3 - '@opentelemetry/api': 1.9.1 + "@next/swc-darwin-arm64": 16.2.3 + "@next/swc-darwin-x64": 16.2.3 + "@next/swc-linux-arm64-gnu": 16.2.3 + "@next/swc-linux-arm64-musl": 16.2.3 + "@next/swc-linux-x64-gnu": 16.2.3 + "@next/swc-linux-x64-musl": 16.2.3 + "@next/swc-win32-arm64-msvc": 16.2.3 + "@next/swc-win32-x64-msvc": 16.2.3 + "@opentelemetry/api": 1.9.1 sharp: 0.34.5 transitivePeerDependencies: - - '@babel/core' + - "@babel/core" - babel-plugin-macros node-addon-api@2.0.2: {} + node-addon-api@7.1.1: {} + node-domexception@1.0.0: {} node-exports-info@1.6.2: @@ -14615,12 +19382,12 @@ snapshots: ox@0.14.29(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 + "@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.4(typescript@5.9.3)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: @@ -14630,12 +19397,12 @@ snapshots: ox@0.14.29(typescript@5.9.3)(zod@4.4.3): 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 + "@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.4(typescript@5.9.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: @@ -14645,11 +19412,11 @@ snapshots: ox@0.6.7(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 + "@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.2.4(typescript@5.9.3)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: @@ -14659,11 +19426,11 @@ snapshots: ox@0.6.7(typescript@5.9.3)(zod@4.4.3): 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 + "@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.2.4(typescript@5.9.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: @@ -14673,11 +19440,11 @@ snapshots: 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 + "@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.2.4(typescript@5.9.3)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: @@ -14687,11 +19454,11 @@ snapshots: ox@0.6.9(typescript@5.9.3)(zod@4.4.3): 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 + "@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.2.4(typescript@5.9.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: @@ -14701,12 +19468,12 @@ snapshots: ox@0.9.17(typescript@5.9.3)(zod@4.4.3): 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 + "@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.4(typescript@5.9.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: @@ -14716,12 +19483,12 @@ snapshots: ox@0.9.6(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 + "@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.1.0(typescript@5.9.3)(zod@3.22.4) eventemitter3: 5.0.1 optionalDependencies: @@ -14731,12 +19498,12 @@ snapshots: ox@0.9.6(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 + "@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.1.0(typescript@5.9.3)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: @@ -14746,12 +19513,12 @@ snapshots: ox@0.9.6(typescript@5.9.3)(zod@4.4.3): 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 + "@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.1.0(typescript@5.9.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: @@ -14761,12 +19528,12 @@ snapshots: ox@https://pkg.pr.new/ox@386a3439fe1ce76d237930f8c6e6bb493746069a(typescript@5.9.3)(zod@4.4.3): 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 + "@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.4(typescript@5.9.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: @@ -14806,7 +19573,7 @@ snapshots: parse-entities@4.0.2: dependencies: - '@types/unist': 2.0.11 + "@types/unist": 2.0.11 character-entities-legacy: 3.0.0 character-reference-invalid: 2.0.1 decode-named-character-reference: 1.3.0 @@ -14816,7 +19583,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.29.7 + "@babel/code-frame": 7.29.7 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -14920,7 +19687,7 @@ snapshots: porto@0.2.35(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(zod@4.4.3)): dependencies: - '@wagmi/core': 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + "@wagmi/core": 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) hono: 4.12.27 idb-keyval: 6.2.6 mipd: 0.0.7(typescript@5.9.3) @@ -14929,18 +19696,18 @@ snapshots: zod: 4.4.3 zustand: 5.0.14(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)) optionalDependencies: - '@tanstack/react-query': 5.101.2(react@19.2.2) + "@tanstack/react-query": 5.101.2(react@19.2.2) react: 19.2.2 typescript: 5.9.3 wagmi: 2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(zod@4.4.3) transitivePeerDependencies: - - '@types/react' + - "@types/react" - immer - use-sync-external-store porto@0.2.35(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)): dependencies: - '@wagmi/core': 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + "@wagmi/core": 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) hono: 4.12.27 idb-keyval: 6.2.6 mipd: 0.0.7(typescript@5.9.3) @@ -14949,12 +19716,12 @@ snapshots: zod: 4.4.3 zustand: 5.0.14(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)) optionalDependencies: - '@tanstack/react-query': 5.101.2(react@19.2.2) + "@tanstack/react-query": 5.101.2(react@19.2.2) react: 19.2.2 typescript: 5.9.3 wagmi: 2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76) transitivePeerDependencies: - - '@types/react' + - "@types/react" - immer - use-sync-external-store @@ -14978,8 +19745,8 @@ snapshots: posthog-js@1.379.3: dependencies: - '@posthog/core': 1.30.6 - '@posthog/types': 1.379.3 + "@posthog/core": 1.30.6 + "@posthog/types": 1.379.3 core-js: 3.49.0 dompurify: 3.4.11 fflate: 0.4.8 @@ -15093,13 +19860,15 @@ snapshots: react-is@16.13.1: {} + react-is@19.2.8: {} + react-remove-scroll-bar@2.3.8(@types/react@19.1.2)(react@19.2.2): dependencies: react: 19.2.2 react-style-singleton: 2.2.3(@types/react@19.1.2)(react@19.2.2) tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react-remove-scroll@2.7.2(@types/react@19.1.2)(react@19.2.2): dependencies: @@ -15110,7 +19879,7 @@ snapshots: use-callback-ref: 1.3.3(@types/react@19.1.2)(react@19.2.2) use-sidecar: 1.1.3(@types/react@19.1.2)(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react-style-singleton@2.2.3(@types/react@19.1.2)(react@19.2.2): dependencies: @@ -15118,7 +19887,13 @@ snapshots: react: 19.2.2 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 + + react-test-renderer@19.2.2(react@19.2.2): + dependencies: + react: 19.2.2 + react-is: 19.2.8 + scheduler: 0.27.0 react-transition-state@1.1.5(react-dom@19.2.2(react@19.2.2))(react@19.2.2): dependencies: @@ -15165,7 +19940,7 @@ snapshots: recma-build-jsx@1.0.0: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 estree-util-build-jsx: 3.0.1 vfile: 6.0.3 @@ -15180,14 +19955,14 @@ snapshots: recma-parse@1.0.0: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 esast-util-from-js: 2.0.1 unified: 11.0.5 vfile: 6.0.3 recma-stringify@1.0.0: dependencies: - '@types/estree': 1.0.9 + "@types/estree": 1.0.9 estree-util-to-js: 2.0.0 unified: 11.0.5 vfile: 6.0.3 @@ -15233,13 +20008,13 @@ snapshots: rehype-parse@9.0.1: dependencies: - '@types/hast': 3.0.4 + "@types/hast": 3.0.4 hast-util-from-html: 2.0.3 unified: 11.0.5 rehype-pretty-code@0.14.3(shiki@1.29.2): dependencies: - '@types/hast': 3.0.4 + "@types/hast": 3.0.4 hast-util-to-string: 3.0.1 parse-numeric-range: 1.3.0 rehype-parse: 9.0.1 @@ -15249,15 +20024,15 @@ snapshots: rehype-recma@1.0.0: dependencies: - '@types/estree': 1.0.9 - '@types/hast': 3.0.4 + "@types/estree": 1.0.9 + "@types/hast": 3.0.4 hast-util-to-estree: 3.1.3 transitivePeerDependencies: - supports-color remark-gfm@4.0.1: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 mdast-util-gfm: 3.1.0 micromark-extension-gfm: 3.0.0 remark-parse: 11.0.0 @@ -15275,7 +20050,7 @@ snapshots: remark-parse@11.0.0: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 mdast-util-from-markdown: 2.0.3 micromark-util-types: 2.0.2 unified: 11.0.5 @@ -15284,21 +20059,21 @@ snapshots: remark-rehype@11.1.2: dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 + "@types/hast": 3.0.4 + "@types/mdast": 4.0.4 mdast-util-to-hast: 13.2.1 unified: 11.0.5 vfile: 6.0.3 remark-stringify@11.0.0: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 mdast-util-to-markdown: 2.1.2 unified: 11.0.5 remark@15.0.1: dependencies: - '@types/mdast': 4.0.4 + "@types/mdast": 4.0.4 remark-parse: 11.0.0 remark-stringify: 11.0.0 unified: 11.0.5 @@ -15352,9 +20127,9 @@ snapshots: rpc-websockets@9.3.9: dependencies: - '@swc/helpers': 0.5.23 - '@types/uuid': 10.0.0 - '@types/ws': 8.18.1 + "@swc/helpers": 0.5.23 + "@types/uuid": 10.0.0 + "@types/ws": 8.18.1 buffer: 6.0.3 eventemitter3: 5.0.4 uuid: 14.0.1 @@ -15467,11 +20242,11 @@ snapshots: shadcn@2.9.3-canary.0(@types/node@20.19.43)(typescript@5.9.3): dependencies: - '@antfu/ni': 23.3.1 - '@babel/core': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7) - '@modelcontextprotocol/sdk': 1.29.0(zod@3.25.76) + "@antfu/ni": 23.3.1 + "@babel/core": 7.29.7 + "@babel/parser": 7.29.7 + "@babel/plugin-transform-typescript": 7.29.7(@babel/core@7.29.7) + "@modelcontextprotocol/sdk": 1.29.0(zod@3.25.76) commander: 10.0.1 cosmiconfig: 8.3.6(typescript@5.9.3) deepmerge: 4.3.1 @@ -15493,8 +20268,8 @@ snapshots: zod: 3.25.76 zod-to-json-schema: 3.25.2(zod@3.25.76) transitivePeerDependencies: - - '@cfworker/json-schema' - - '@types/node' + - "@cfworker/json-schema" + - "@types/node" - supports-color - typescript @@ -15502,34 +20277,34 @@ snapshots: sharp@0.34.5: dependencies: - '@img/colour': 1.1.0 + "@img/colour": 1.1.0 detect-libc: 2.1.2 semver: 7.8.5 optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.5 - '@img/sharp-darwin-x64': 0.34.5 - '@img/sharp-libvips-darwin-arm64': 1.2.4 - '@img/sharp-libvips-darwin-x64': 1.2.4 - '@img/sharp-libvips-linux-arm': 1.2.4 - '@img/sharp-libvips-linux-arm64': 1.2.4 - '@img/sharp-libvips-linux-ppc64': 1.2.4 - '@img/sharp-libvips-linux-riscv64': 1.2.4 - '@img/sharp-libvips-linux-s390x': 1.2.4 - '@img/sharp-libvips-linux-x64': 1.2.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - '@img/sharp-linux-arm': 0.34.5 - '@img/sharp-linux-arm64': 0.34.5 - '@img/sharp-linux-ppc64': 0.34.5 - '@img/sharp-linux-riscv64': 0.34.5 - '@img/sharp-linux-s390x': 0.34.5 - '@img/sharp-linux-x64': 0.34.5 - '@img/sharp-linuxmusl-arm64': 0.34.5 - '@img/sharp-linuxmusl-x64': 0.34.5 - '@img/sharp-wasm32': 0.34.5 - '@img/sharp-win32-arm64': 0.34.5 - '@img/sharp-win32-ia32': 0.34.5 - '@img/sharp-win32-x64': 0.34.5 + "@img/sharp-darwin-arm64": 0.34.5 + "@img/sharp-darwin-x64": 0.34.5 + "@img/sharp-libvips-darwin-arm64": 1.2.4 + "@img/sharp-libvips-darwin-x64": 1.2.4 + "@img/sharp-libvips-linux-arm": 1.2.4 + "@img/sharp-libvips-linux-arm64": 1.2.4 + "@img/sharp-libvips-linux-ppc64": 1.2.4 + "@img/sharp-libvips-linux-riscv64": 1.2.4 + "@img/sharp-libvips-linux-s390x": 1.2.4 + "@img/sharp-libvips-linux-x64": 1.2.4 + "@img/sharp-libvips-linuxmusl-arm64": 1.2.4 + "@img/sharp-libvips-linuxmusl-x64": 1.2.4 + "@img/sharp-linux-arm": 0.34.5 + "@img/sharp-linux-arm64": 0.34.5 + "@img/sharp-linux-ppc64": 0.34.5 + "@img/sharp-linux-riscv64": 0.34.5 + "@img/sharp-linux-s390x": 0.34.5 + "@img/sharp-linux-x64": 0.34.5 + "@img/sharp-linuxmusl-arm64": 0.34.5 + "@img/sharp-linuxmusl-x64": 0.34.5 + "@img/sharp-wasm32": 0.34.5 + "@img/sharp-win32-arm64": 0.34.5 + "@img/sharp-win32-ia32": 0.34.5 + "@img/sharp-win32-x64": 0.34.5 optional: true shebang-command@2.0.0: @@ -15540,25 +20315,25 @@ snapshots: shiki@1.29.2: dependencies: - '@shikijs/core': 1.29.2 - '@shikijs/engine-javascript': 1.29.2 - '@shikijs/engine-oniguruma': 1.29.2 - '@shikijs/langs': 1.29.2 - '@shikijs/themes': 1.29.2 - '@shikijs/types': 1.29.2 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + "@shikijs/core": 1.29.2 + "@shikijs/engine-javascript": 1.29.2 + "@shikijs/engine-oniguruma": 1.29.2 + "@shikijs/langs": 1.29.2 + "@shikijs/themes": 1.29.2 + "@shikijs/types": 1.29.2 + "@shikijs/vscode-textmate": 10.0.2 + "@types/hast": 3.0.4 shiki@4.3.0: dependencies: - '@shikijs/core': 4.3.0 - '@shikijs/engine-javascript': 4.3.0 - '@shikijs/engine-oniguruma': 4.3.0 - '@shikijs/langs': 4.3.0 - '@shikijs/themes': 4.3.0 - '@shikijs/types': 4.3.0 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 + "@shikijs/core": 4.3.0 + "@shikijs/engine-javascript": 4.3.0 + "@shikijs/engine-oniguruma": 4.3.0 + "@shikijs/langs": 4.3.0 + "@shikijs/themes": 4.3.0 + "@shikijs/types": 4.3.0 + "@shikijs/vscode-textmate": 10.0.2 + "@types/hast": 3.0.4 side-channel-list@1.0.1: dependencies: @@ -15596,7 +20371,7 @@ snapshots: socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@5.0.10): dependencies: - '@socket.io/component-emitter': 3.1.2 + "@socket.io/component-emitter": 3.1.2 debug: 4.4.3(supports-color@5.5.0) engine.io-client: 6.6.6(bufferutil@4.1.0)(utf-8-validate@5.0.10) socket.io-parser: 4.2.6 @@ -15607,7 +20382,7 @@ snapshots: socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6): dependencies: - '@socket.io/component-emitter': 3.1.2 + "@socket.io/component-emitter": 3.1.2 debug: 4.4.3(supports-color@5.5.0) engine.io-client: 6.6.6(bufferutil@4.1.0)(utf-8-validate@6.0.6) socket.io-parser: 4.2.6 @@ -15618,7 +20393,7 @@ snapshots: socket.io-parser@4.2.6: dependencies: - '@socket.io/component-emitter': 3.1.2 + "@socket.io/component-emitter": 3.1.2 debug: 4.4.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -15785,30 +20560,30 @@ snapshots: hey-listen: 1.0.8 tslib: 2.8.1 - styled-components@5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@16.13.1)(react@19.2.2): + styled-components@5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@19.2.8)(react@19.2.2): dependencies: - '@babel/helper-module-imports': 7.29.7(supports-color@5.5.0) - '@babel/traverse': 7.29.7(supports-color@5.5.0) - '@emotion/is-prop-valid': 1.4.0 - '@emotion/stylis': 0.8.5 - '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.3.0(@babel/core@7.29.7)(styled-components@5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@16.13.1)(react@19.2.2))(supports-color@5.5.0) + "@babel/helper-module-imports": 7.29.7(supports-color@5.5.0) + "@babel/traverse": 7.29.7(supports-color@5.5.0) + "@emotion/is-prop-valid": 1.4.0 + "@emotion/stylis": 0.8.5 + "@emotion/unitless": 0.7.5 + babel-plugin-styled-components: 2.3.0(@babel/core@7.29.7)(styled-components@5.3.11(@babel/core@7.29.7)(react-dom@19.2.2(react@19.2.2))(react-is@19.2.8)(react@19.2.2))(supports-color@5.5.0) css-to-react-native: 3.2.0 hoist-non-react-statics: 3.3.2 react: 19.2.2 react-dom: 19.2.2(react@19.2.2) - react-is: 16.13.1 + react-is: 19.2.8 shallowequal: 1.1.0 supports-color: 5.5.0 transitivePeerDependencies: - - '@babel/core' + - "@babel/core" styled-jsx@5.1.6(@babel/core@7.29.7)(react@19.2.2): dependencies: client-only: 0.0.1 react: 19.2.2 optionalDependencies: - '@babel/core': 7.29.7 + "@babel/core": 7.29.7 superstruct@1.0.4: {} @@ -15830,6 +20605,8 @@ snapshots: tailwindcss@4.3.2: {} + tailwindcss@4.3.3: {} + tapable@2.3.3: {} text-encoding-utf-8@1.0.2: {} @@ -15881,17 +20658,17 @@ snapshots: ts-morph@18.0.0: dependencies: - '@ts-morph/common': 0.19.0 + "@ts-morph/common": 0.19.0 code-block-writer: 12.0.0 ts-node@10.9.2(@types/node@20.19.43)(typescript@5.9.3): dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 20.19.43 + "@cspotcode/source-map-support": 0.8.1 + "@tsconfig/node10": 1.0.12 + "@tsconfig/node12": 1.0.11 + "@tsconfig/node14": 1.0.3 + "@tsconfig/node16": 1.0.4 + "@types/node": 20.19.43 acorn: 8.17.0 acorn-walk: 8.3.5 arg: 4.1.3 @@ -15904,7 +20681,7 @@ snapshots: tsconfig-paths@3.15.0: dependencies: - '@types/json5': 0.0.29 + "@types/json5": 0.0.29 json5: 1.0.2 minimist: 1.2.8 strip-bom: 3.0.0 @@ -15978,10 +20755,10 @@ snapshots: typescript-eslint@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.62.1(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) - '@typescript-eslint/parser': 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.62.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + "@typescript-eslint/eslint-plugin": 8.62.1(@typescript-eslint/parser@8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + "@typescript-eslint/parser": 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + "@typescript-eslint/typescript-estree": 8.62.1(typescript@5.9.3) + "@typescript-eslint/utils": 8.62.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) eslint: 9.39.4(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: @@ -16012,7 +20789,7 @@ snapshots: unified@11.0.5: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 bail: 2.0.2 devlop: 1.1.0 extend: 3.0.2 @@ -16022,33 +20799,33 @@ snapshots: unist-util-is@6.0.1: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 unist-util-position-from-estree@2.0.0: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 unist-util-position@5.0.0: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 unist-util-remove-position@5.0.0: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 unist-util-visit: 5.1.0 unist-util-stringify-position@4.0.0: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 unist-util-visit-parents@6.0.2: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 unist-util-is: 6.0.1 unist-util-visit@5.1.0: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 @@ -16060,28 +20837,28 @@ snapshots: dependencies: napi-postinstall: 0.3.4 optionalDependencies: - '@unrs/resolver-binding-android-arm-eabi': 1.12.2 - '@unrs/resolver-binding-android-arm64': 1.12.2 - '@unrs/resolver-binding-darwin-arm64': 1.12.2 - '@unrs/resolver-binding-darwin-x64': 1.12.2 - '@unrs/resolver-binding-freebsd-x64': 1.12.2 - '@unrs/resolver-binding-linux-arm-gnueabihf': 1.12.2 - '@unrs/resolver-binding-linux-arm-musleabihf': 1.12.2 - '@unrs/resolver-binding-linux-arm64-gnu': 1.12.2 - '@unrs/resolver-binding-linux-arm64-musl': 1.12.2 - '@unrs/resolver-binding-linux-loong64-gnu': 1.12.2 - '@unrs/resolver-binding-linux-loong64-musl': 1.12.2 - '@unrs/resolver-binding-linux-ppc64-gnu': 1.12.2 - '@unrs/resolver-binding-linux-riscv64-gnu': 1.12.2 - '@unrs/resolver-binding-linux-riscv64-musl': 1.12.2 - '@unrs/resolver-binding-linux-s390x-gnu': 1.12.2 - '@unrs/resolver-binding-linux-x64-gnu': 1.12.2 - '@unrs/resolver-binding-linux-x64-musl': 1.12.2 - '@unrs/resolver-binding-openharmony-arm64': 1.12.2 - '@unrs/resolver-binding-wasm32-wasi': 1.12.2 - '@unrs/resolver-binding-win32-arm64-msvc': 1.12.2 - '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2 - '@unrs/resolver-binding-win32-x64-msvc': 1.12.2 + "@unrs/resolver-binding-android-arm-eabi": 1.12.2 + "@unrs/resolver-binding-android-arm64": 1.12.2 + "@unrs/resolver-binding-darwin-arm64": 1.12.2 + "@unrs/resolver-binding-darwin-x64": 1.12.2 + "@unrs/resolver-binding-freebsd-x64": 1.12.2 + "@unrs/resolver-binding-linux-arm-gnueabihf": 1.12.2 + "@unrs/resolver-binding-linux-arm-musleabihf": 1.12.2 + "@unrs/resolver-binding-linux-arm64-gnu": 1.12.2 + "@unrs/resolver-binding-linux-arm64-musl": 1.12.2 + "@unrs/resolver-binding-linux-loong64-gnu": 1.12.2 + "@unrs/resolver-binding-linux-loong64-musl": 1.12.2 + "@unrs/resolver-binding-linux-ppc64-gnu": 1.12.2 + "@unrs/resolver-binding-linux-riscv64-gnu": 1.12.2 + "@unrs/resolver-binding-linux-riscv64-musl": 1.12.2 + "@unrs/resolver-binding-linux-s390x-gnu": 1.12.2 + "@unrs/resolver-binding-linux-x64-gnu": 1.12.2 + "@unrs/resolver-binding-linux-x64-musl": 1.12.2 + "@unrs/resolver-binding-openharmony-arm64": 1.12.2 + "@unrs/resolver-binding-wasm32-wasi": 1.12.2 + "@unrs/resolver-binding-win32-arm64-msvc": 1.12.2 + "@unrs/resolver-binding-win32-ia32-msvc": 1.12.2 + "@unrs/resolver-binding-win32-x64-msvc": 1.12.2 unstorage@1.17.5(idb-keyval@6.2.6): dependencies: @@ -16113,7 +20890,7 @@ snapshots: react: 19.2.2 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 use-sidecar@1.1.3(@types/react@19.1.2)(react@19.2.2): dependencies: @@ -16121,7 +20898,7 @@ snapshots: react: 19.2.2 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 use-sync-external-store@1.2.0(react@19.2.2): dependencies: @@ -16168,32 +20945,32 @@ snapshots: proxy-compare: 2.6.0 use-sync-external-store: 1.2.0(react@19.2.2) optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: 19.2.2 vary@1.1.2: {} vfile-location@5.0.3: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 vfile: 6.0.3 vfile-message@4.0.3: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 unist-util-stringify-position: 4.0.0 vfile@6.0.3: dependencies: - '@types/unist': 3.0.3 + "@types/unist": 3.0.3 vfile-message: 4.0.3 viem@2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3): dependencies: - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@scure/bip32': 1.6.2 - '@scure/bip39': 1.5.4 + "@noble/curves": 1.8.1 + "@noble/hashes": 1.7.1 + "@scure/bip32": 1.6.2 + "@scure/bip39": 1.5.4 abitype: 1.0.8(typescript@5.9.3)(zod@4.4.3) isows: 1.0.6(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ox: 0.6.7(typescript@5.9.3)(zod@4.4.3) @@ -16207,10 +20984,10 @@ snapshots: viem@2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76): dependencies: - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@scure/bip32': 1.6.2 - '@scure/bip39': 1.5.4 + "@noble/curves": 1.8.1 + "@noble/hashes": 1.7.1 + "@scure/bip32": 1.6.2 + "@scure/bip39": 1.5.4 abitype: 1.0.8(typescript@5.9.3)(zod@3.25.76) isows: 1.0.6(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ox: 0.6.7(typescript@5.9.3)(zod@3.25.76) @@ -16224,10 +21001,10 @@ snapshots: viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(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 + "@noble/curves": 1.9.1 + "@noble/hashes": 1.8.0 + "@scure/bip32": 1.7.0 + "@scure/bip39": 1.6.0 abitype: 1.1.0(typescript@5.9.3)(zod@3.22.4) isows: 1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10)) ox: 0.9.6(typescript@5.9.3)(zod@3.22.4) @@ -16241,10 +21018,10 @@ snapshots: viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3): dependencies: - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 + "@noble/curves": 1.9.1 + "@noble/hashes": 1.8.0 + "@scure/bip32": 1.7.0 + "@scure/bip39": 1.6.0 abitype: 1.1.0(typescript@5.9.3)(zod@4.4.3) isows: 1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10)) ox: 0.9.6(typescript@5.9.3)(zod@4.4.3) @@ -16258,10 +21035,10 @@ snapshots: viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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 + "@noble/curves": 1.9.1 + "@noble/hashes": 1.8.0 + "@scure/bip32": 1.7.0 + "@scure/bip39": 1.6.0 abitype: 1.1.0(typescript@5.9.3)(zod@3.22.4) isows: 1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ox: 0.9.6(typescript@5.9.3)(zod@3.22.4) @@ -16275,10 +21052,10 @@ snapshots: viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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 + "@noble/curves": 1.9.1 + "@noble/hashes": 1.8.0 + "@scure/bip32": 1.7.0 + "@scure/bip39": 1.6.0 abitype: 1.1.0(typescript@5.9.3)(zod@3.25.76) isows: 1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ox: 0.9.6(typescript@5.9.3)(zod@3.25.76) @@ -16292,10 +21069,10 @@ snapshots: viem@2.51.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3): dependencies: - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.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@4.4.3) isows: 1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@5.0.10)) ox: https://pkg.pr.new/ox@386a3439fe1ce76d237930f8c6e6bb493746069a(typescript@5.9.3)(zod@4.4.3) @@ -16309,10 +21086,10 @@ snapshots: viem@2.51.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.4.3): dependencies: - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.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@4.4.3) isows: 1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ox: https://pkg.pr.new/ox@386a3439fe1ce76d237930f8c6e6bb493746069a(typescript@5.9.3)(zod@4.4.3) @@ -16326,10 +21103,10 @@ snapshots: viem@2.54.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(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 + "@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.20.1(bufferutil@4.1.0)(utf-8-validate@5.0.10)) ox: 0.14.29(typescript@5.9.3)(zod@3.25.76) @@ -16343,10 +21120,10 @@ snapshots: viem@2.54.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3): dependencies: - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.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@4.4.3) isows: 1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@5.0.10)) ox: 0.14.29(typescript@5.9.3)(zod@4.4.3) @@ -16360,10 +21137,10 @@ snapshots: viem@2.54.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(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 + "@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.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ox: 0.14.29(typescript@5.9.3)(zod@3.25.76) @@ -16377,10 +21154,10 @@ snapshots: viem@2.54.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.4.3): dependencies: - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.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@4.4.3) isows: 1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ox: 0.14.29(typescript@5.9.3)(zod@4.4.3) @@ -16394,32 +21171,32 @@ snapshots: wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(zod@4.4.3): dependencies: - '@tanstack/react-query': 5.101.2(react@19.2.2) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(zod@4.4.3))(zod@4.4.3) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)) + "@tanstack/react-query": 5.101.2(react@19.2.2) + "@wagmi/connectors": 6.2.0(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3))(zod@4.4.3))(zod@4.4.3) + "@wagmi/core": 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3)) react: 19.2.2 use-sync-external-store: 1.4.0(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@4.4.3) optionalDependencies: 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' - - '@tanstack/query-core' - - '@types/react' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' + - "@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" + - "@tanstack/query-core" + - "@types/react" + - "@upstash/redis" + - "@vercel/blob" + - "@vercel/functions" + - "@vercel/kv" - aws4fetch - bufferutil - db0 @@ -16439,32 +21216,32 @@ snapshots: wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76): dependencies: - '@tanstack/react-query': 5.101.2(react@19.2.2) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + "@tanstack/react-query": 5.101.2(react@19.2.2) + "@wagmi/connectors": 6.2.0(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@19.2.2))(@types/react@19.1.2)(bufferutil@4.1.0)(react@19.2.2)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) + "@wagmi/core": 2.22.1(@tanstack/query-core@5.101.2)(@types/react@19.1.2)(react@19.2.2)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.2))(viem@2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) react: 19.2.2 use-sync-external-store: 1.4.0(react@19.2.2) viem: 2.38.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) optionalDependencies: 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' - - '@tanstack/query-core' - - '@types/react' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' + - "@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" + - "@tanstack/query-core" + - "@types/react" + - "@upstash/redis" + - "@vercel/blob" + - "@vercel/functions" + - "@vercel/kv" - aws4fetch - bufferutil - db0 @@ -16675,19 +21452,19 @@ snapshots: zustand@5.0.0(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)): optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: 19.2.2 use-sync-external-store: 1.4.0(react@19.2.2) zustand@5.0.14(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)): optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: 19.2.2 use-sync-external-store: 1.4.0(react@19.2.2) zustand@5.0.3(@types/react@19.1.2)(react@19.2.2)(use-sync-external-store@1.4.0(react@19.2.2)): optionalDependencies: - '@types/react': 19.1.2 + "@types/react": 19.1.2 react: 19.2.2 use-sync-external-store: 1.4.0(react@19.2.2) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 9eb468f3..84305d6f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -7,6 +7,7 @@ allowBuilds: "@avail-project/ca-common": true "@avail-project/nexus-core": true "@avail-project/nexus-types": true + '@parcel/watcher': true bufferutil: true core-js: true esbuild: true diff --git a/public/r/bridge-deposit.json b/public/r/bridge-deposit.json index 5200a757..20b83b11 100644 --- a/public/r/bridge-deposit.json +++ b/public/r/bridge-deposit.json @@ -5,7 +5,7 @@ "title": "Bridge Deposit", "description": "Deprecated: use Nexus Widget instead. Bridge Deposit has been removed in favor of Nexus Widget deposit mode.", "dependencies": [ - "@avail-project/nexus-core@2.2.3", + "@avail-project/nexus-core@2.5.0", "lucide-react", "viem" ], @@ -202,7 +202,7 @@ }, { "path": "registry/avail-widgets/common/utils/constant.ts", - "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", + "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n ARC: 5042,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n [SUPPORTED_CHAINS.ARC]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arc/logo.png\",\n name: \"Arc\",\n nativeCurrency: { name: \"USDC\", symbol: \"USDC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.arc.market\"],\n rpcUrls: [\"https://rpc.arc.market\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n [SUPPORTED_CHAINS.ARC]: \"Arc\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 5042: \"0x0000000000000000000000000000000000000000\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", "type": "registry:component", "target": "components/common/utils/constant.ts" }, @@ -214,7 +214,7 @@ }, { "path": "registry/avail-widgets/common/utils/transaction-flow.ts", - "content": "import {\n type NexusNetwork,\n type NexusClient,\n} from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n chainId === SUPPORTED_CHAINS.BNB\n ) {\n return 18;\n }\n return fallback;\n};\n", + "content": "import { type NexusNetwork, type NexusClient } from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n (chainId === SUPPORTED_CHAINS.BNB || chainId === SUPPORTED_CHAINS.ARC)\n ) {\n return 18;\n }\n return fallback;\n};\n", "type": "registry:component", "target": "components/common/utils/transaction-flow.ts" } diff --git a/public/r/deposit.json b/public/r/deposit.json index 41c483fc..fc48191b 100644 --- a/public/r/deposit.json +++ b/public/r/deposit.json @@ -5,7 +5,7 @@ "title": "Deposit", "description": "Deprecated: use Nexus Widget instead. A legacy component built with Nexus to enable deposits.", "dependencies": [ - "@avail-project/nexus-core@2.2.3", + "@avail-project/nexus-core@2.5.0", "clsx", "lucide-react", "tailwind-merge", @@ -315,7 +315,7 @@ }, { "path": "registry/avail-widgets/common/utils/constant.ts", - "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", + "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n ARC: 5042,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n [SUPPORTED_CHAINS.ARC]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arc/logo.png\",\n name: \"Arc\",\n nativeCurrency: { name: \"USDC\", symbol: \"USDC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.arc.market\"],\n rpcUrls: [\"https://rpc.arc.market\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n [SUPPORTED_CHAINS.ARC]: \"Arc\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 5042: \"0x0000000000000000000000000000000000000000\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", "type": "registry:component", "target": "components/common/utils/constant.ts" }, @@ -327,7 +327,7 @@ }, { "path": "registry/avail-widgets/common/utils/transaction-flow.ts", - "content": "import {\n type NexusNetwork,\n type NexusClient,\n} from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n chainId === SUPPORTED_CHAINS.BNB\n ) {\n return 18;\n }\n return fallback;\n};\n", + "content": "import { type NexusNetwork, type NexusClient } from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n (chainId === SUPPORTED_CHAINS.BNB || chainId === SUPPORTED_CHAINS.ARC)\n ) {\n return 18;\n }\n return fallback;\n};\n", "type": "registry:component", "target": "components/common/utils/transaction-flow.ts" } diff --git a/public/r/fast-bridge.json b/public/r/fast-bridge.json index 3823c06a..5de473ad 100644 --- a/public/r/fast-bridge.json +++ b/public/r/fast-bridge.json @@ -5,7 +5,7 @@ "title": "Fast Bridge", "description": "Deprecated: use Nexus Widget instead. A legacy component built with Nexus to enable cross chain bridging.", "dependencies": [ - "@avail-project/nexus-core@2.2.3", + "@avail-project/nexus-core@2.5.0", "lucide-react", "viem" ], @@ -183,7 +183,7 @@ }, { "path": "registry/avail-widgets/common/utils/constant.ts", - "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", + "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n ARC: 5042,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n [SUPPORTED_CHAINS.ARC]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arc/logo.png\",\n name: \"Arc\",\n nativeCurrency: { name: \"USDC\", symbol: \"USDC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.arc.market\"],\n rpcUrls: [\"https://rpc.arc.market\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n [SUPPORTED_CHAINS.ARC]: \"Arc\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 5042: \"0x0000000000000000000000000000000000000000\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", "type": "registry:component", "target": "components/common/utils/constant.ts" }, @@ -195,7 +195,7 @@ }, { "path": "registry/avail-widgets/common/utils/transaction-flow.ts", - "content": "import {\n type NexusNetwork,\n type NexusClient,\n} from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n chainId === SUPPORTED_CHAINS.BNB\n ) {\n return 18;\n }\n return fallback;\n};\n", + "content": "import { type NexusNetwork, type NexusClient } from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n (chainId === SUPPORTED_CHAINS.BNB || chainId === SUPPORTED_CHAINS.ARC)\n ) {\n return 18;\n }\n return fallback;\n};\n", "type": "registry:component", "target": "components/common/utils/transaction-flow.ts" } diff --git a/public/r/nexus-provider.json b/public/r/nexus-provider.json index 0c3d8fdf..8f65b5fc 100644 --- a/public/r/nexus-provider.json +++ b/public/r/nexus-provider.json @@ -5,7 +5,7 @@ "title": "Nexus Provider", "description": "Shared Nexus SDK provider and types for Avail Widgets", "dependencies": [ - "@avail-project/nexus-core@2.2.3", + "@avail-project/nexus-core@2.5.0", "wagmi" ], "files": [ diff --git a/public/r/nexus.json b/public/r/nexus.json index d6426d22..1e37129d 100644 --- a/public/r/nexus.json +++ b/public/r/nexus.json @@ -5,7 +5,7 @@ "title": "Nexus Widget", "description": "The unified Avail Nexus widget for swap, send, and deposit flows. One component for all cross-chain operations powered by Nexus intents.", "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "decimal.js", "lucide-react", "viem", @@ -30,18 +30,36 @@ "type": "registry:component", "target": "components/nexus/components/amount-input-unified.tsx" }, + { + "path": "registry/avail-widgets/nexus-widget/components/deposit-funding-method.tsx", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport React from \"react\";\nimport { nexusWidgetTheme } from \"../theme\";\n\ntype FundingMethod = \"wallet\" | \"local-currency\";\n\ninterface DepositFundingMethodProps {\n enableOnRamp?: boolean;\n isBalanceLoading?: boolean;\n onSelectLocalCurrency: () => void;\n onSelectWallet: () => void;\n primaryButtonForeground: string;\n totalBalance: string;\n}\n\ninterface LogoItem {\n alt: string;\n height?: string;\n invertDark?: boolean;\n url: string;\n width?: string;\n}\n\nconst WALLET_LOGOS: LogoItem[] = [\n {\n alt: \"MetaMask\",\n height: \"22px\",\n url: \"https://files.availproject.org/widgets/assets/metamask.png\",\n width: \"22px\",\n },\n {\n alt: \"Rabby\",\n height: \"22px\",\n url: \"https://files.availproject.org/widgets/assets/rabby.png\",\n width: \"22px\",\n },\n {\n alt: \"Zerion\",\n height: \"20px\",\n url: \"https://files.availproject.org/widgets/assets/zerion.png\",\n width: \"20px\",\n },\n];\n\nconst CASH_LOGOS: LogoItem[] = [\n {\n alt: \"Mastercard\",\n height: \"15px\",\n url: \"https://files.availproject.org/widgets/assets/mastercard.png\",\n width: \"24px\",\n },\n {\n alt: \"Apple Pay\",\n height: \"20px\",\n invertDark: true,\n url: \"https://files.availproject.org/widgets/assets/apple-pay.png\",\n width: \"20px\",\n },\n {\n alt: \"Google Pay\",\n height: \"20px\",\n url: \"https://files.availproject.org/widgets/assets/google-pay.png\",\n width: \"20px\",\n },\n];\n\nconst theme = nexusWidgetTheme;\nconst brand = \"var(--foreground-brand)\";\n\nconst useIsDarkMode = () => {\n const [isDark, setIsDark] = React.useState(false);\n\n React.useEffect(() => {\n if (typeof window === \"undefined\" || typeof document === \"undefined\")\n return;\n\n const checkDark = () => {\n const root =\n typeof document !== \"undefined\" ? document.documentElement : undefined;\n const body = typeof document !== \"undefined\" ? document.body : undefined;\n const isDarkClass = Boolean(\n root?.classList?.contains(\"dark\") || body?.classList?.contains(\"dark\"),\n );\n const isDataThemeDark = root?.getAttribute?.(\"data-theme\") === \"dark\";\n const prefersDark =\n typeof window.matchMedia === \"function\"\n ? Boolean(window.matchMedia(\"(prefers-color-scheme: dark)\")?.matches)\n : false;\n return Boolean(isDarkClass || isDataThemeDark || prefersDark);\n };\n\n setIsDark(checkDark());\n\n const mediaQuery =\n typeof window.matchMedia === \"function\"\n ? window.matchMedia(\"(prefers-color-scheme: dark)\")\n : undefined;\n const handleMediaChange = () => setIsDark(checkDark());\n mediaQuery?.addEventListener?.(\"change\", handleMediaChange);\n\n const root =\n typeof document !== \"undefined\" ? document.documentElement : undefined;\n let observer: MutationObserver | undefined;\n if (root && typeof MutationObserver !== \"undefined\") {\n observer = new MutationObserver(() => {\n setIsDark(checkDark());\n });\n observer.observe(root, {\n attributes: true,\n attributeFilter: [\"class\", \"data-theme\"],\n });\n }\n\n return () => {\n mediaQuery?.removeEventListener?.(\"change\", handleMediaChange);\n observer?.disconnect();\n };\n }, []);\n\n return isDark;\n};\n\nfunction RadioMark({ selected }: { selected: boolean }) {\n return (\n \n );\n}\n\nfunction AmountSkeleton({\n height = \"14px\",\n width = \"48px\",\n}: {\n height?: string;\n width?: string;\n}) {\n return (\n \n );\n}\n\nfunction LogoStack({\n isDark,\n items,\n}: {\n isDark: boolean;\n items: LogoItem[];\n}) {\n return (\n \n \n {items.map((item, index) => (\n \n \n
\n ))}\n \n \n );\n}\n\nfunction FundingOption({\n active,\n amount,\n amountLoading = false,\n description,\n hasDivider = false,\n isDark = false,\n label,\n logos,\n onClick,\n}: {\n active: boolean;\n amount?: string;\n amountLoading?: boolean;\n description: string;\n hasDivider?: boolean;\n isDark?: boolean;\n label: string;\n logos: LogoItem[];\n onClick: () => void;\n}) {\n const [isHovered, setIsHovered] = React.useState(false);\n\n return (\n setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n style={{\n alignItems: \"center\",\n backgroundColor: isHovered\n ? isDark\n ? \"rgba(255, 255, 255, 0.04)\"\n : \"#FBFBFA\"\n : theme.colors.surface,\n border: \"none\",\n borderBottom: hasDivider ? `1px solid ${theme.colors.divider}` : \"none\",\n boxSizing: \"border-box\",\n cursor: \"pointer\",\n display: \"flex\",\n gap: \"12px\",\n paddingBlock: \"14px\",\n paddingInline: \"16px\",\n textAlign: \"left\",\n transition: \"background-color 150ms ease\",\n width: \"100%\",\n }}\n type=\"button\"\n >\n \n \n \n {label}\n \n \n {amountLoading ? (\n <>\n Wallet balance: \n \n \n ) : amount !== undefined ? (\n `Wallet balance: $${amount || \"0.00\"}`\n ) : (\n description\n )}\n \n \n \n \n );\n}\n\nexport function DepositFundingMethod({\n enableOnRamp = false,\n isBalanceLoading = false,\n onSelectLocalCurrency,\n onSelectWallet,\n primaryButtonForeground,\n totalBalance,\n}: DepositFundingMethodProps) {\n const [selectedMethod, setSelectedMethod] =\n React.useState(null);\n const isDark = useIsDarkMode();\n\n React.useEffect(() => {\n if (!enableOnRamp) {\n setSelectedMethod((current) =>\n current === \"local-currency\" ? null : current,\n );\n }\n }, [enableOnRamp]);\n\n const handleContinue = () => {\n if (!selectedMethod) return;\n if (selectedMethod === \"wallet\") {\n onSelectWallet();\n return;\n }\n if (enableOnRamp) onSelectLocalCurrency();\n };\n\n return (\n \n \n {\n setSelectedMethod(\"wallet\");\n }}\n />\n {enableOnRamp && (\n {\n setSelectedMethod(\"local-currency\");\n }}\n />\n )}\n \n\n \n \n \n Continue\n \n \n \n \n );\n}\n", + "type": "registry:component", + "target": "components/nexus/components/deposit-funding-method.tsx" + }, { "path": "registry/avail-widgets/nexus-widget/components/deposit-idle-form.tsx", - "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport Decimal from \"decimal.js\";\nimport { AlertCircle, ChevronDown, Loader2 } from \"lucide-react\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport { useNexusWidgetThemeStyle } from \"../theme-context\";\nimport React, { useRef, useState } from \"react\";\nimport { PayWithSources as SharedPayWithSources } from \"./pay-with-sources\";\nimport {\n formatSelectedTokenBalanceLabel,\n formatUsdBalanceLabel,\n type SwapTokenOption,\n} from \"./swap-asset-selector\";\n\ninterface DepositIdleFormProps {\n amount: string;\n amountMode: \"token\" | \"usd\";\n calculatingPercent?: number | null;\n fromTokens: SwapTokenOption[];\n isAmountReadOnly?: boolean;\n isBalanceLoading?: boolean;\n isCalculatingMax?: boolean;\n isQuoteRefreshing?: boolean;\n isSourcePickerDisabled?: boolean;\n isTokenPickerDisabled?: boolean;\n hideDestinationTokenDropdownIcon?: boolean;\n onAmountChange: (val: string) => void;\n onAmountModeToggle: () => void;\n onOpenSourcePicker: () => void;\n onOpenTokenPicker?: () => void;\n onSetPercent: (pct: number) => void;\n reserveSourceRows?: boolean;\n routeMessage?: string;\n routeStatus?: \"loading\" | \"insufficient\";\n showAutoBadge?: boolean;\n tokenValue: string;\n toToken?: SwapTokenOption;\n totalBalance: string;\n usdValue: string;\n}\n\nconst uiFont = '\"Geist\", system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\n\nconst formatToken = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst formatUsd = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n return `$${amount.toDecimalPlaces(2).toFixed()}`;\n};\n\nconst MAX_AMOUNT_DISPLAY_DECIMALS = 8;\nconst getTokenInputDecimals = (token?: Pick) => {\n const decimals = Number(token?.decimals);\n return Number.isFinite(decimals) && decimals >= 0 ? Math.floor(decimals) : 18;\n};\n\nconst formatAmountInputDisplay = (value: string) => {\n if (!value) return \"\";\n try {\n return new Decimal(value)\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n } catch {\n return value;\n }\n};\n\nconst sanitizeAmountInput = (raw: string, maxDecimals: number) => {\n let next = raw.replaceAll(/[^0-9.]/g, \"\");\n const parts = next.split(\".\");\n if (parts.length > 2) next = parts[0] + \".\" + parts.slice(1).join(\"\");\n const [integerPart, decimalPart] = next.split(\".\");\n if (decimalPart !== undefined) {\n next = `${integerPart}.${decimalPart.slice(0, Math.max(0, maxDecimals))}`;\n }\n if (next === \".\") next = \"0.\";\n return next;\n};\n\nfunction TokenLogo({\n src,\n label,\n size = 30,\n fontSize = 12,\n style,\n}: {\n src?: string;\n label?: string;\n size?: number;\n fontSize?: number;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n React.useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction SourceLogoPair({ token }: { token: SwapTokenOption }) {\n return (\n
\n \n {token.chainLogo && (\n \n )}\n
\n );\n}\n\nfunction ExactOutPercentButtons({\n visible,\n onSelect,\n selectedPercent,\n}: {\n visible: boolean;\n onSelect: (pct: number) => void;\n selectedPercent: number | null;\n}) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [focusedPercent, setFocusedPercent] = useState(null);\n\n React.useEffect(() => {\n if (!visible) setFocusedPercent(null);\n }, [visible]);\n\n return (\n \n {[25, 50, 75, 100].map((pct) => {\n const isMax = pct === 100;\n const isFocused = focusedPercent === pct;\n return (\n {\n e.stopPropagation();\n onSelect(pct);\n }}\n onBlur={() => setFocusedPercent(null)}\n onFocus={() => setFocusedPercent(pct)}\n style={{\n alignItems: \"center\",\n backgroundColor: isFocused ? \"var(--nexus-widget-primary-soft, #E8F0FF)\" : \"var(--nexus-widget-surface-raised, #F4F4F3)\",\n border: \"none\",\n borderRadius: \"8px\",\n boxSizing: \"border-box\",\n color: isFocused ? brand : \"var(--nexus-widget-text, #363635)\",\n cursor: \"pointer\",\n display: \"flex\",\n flex: \"1 1 0%\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"12px\",\n fontWeight: 500,\n justifyContent: \"center\",\n lineHeight: \"20px\",\n minWidth: 0,\n paddingBlock: \"5px\",\n paddingInline: \"10px\",\n }}\n type=\"button\"\n >\n {isMax ? \"MAX\" : `${pct}%`}\n \n );\n })}\n \n );\n}\n\nfunction SkeletonRow() {\n return (\n \n \n \n \n );\n}\n\nfunction PayWithSources({\n fromTokens,\n onOpenSourcePicker,\n routeStatus,\n routeMessage,\n}: {\n fromTokens: SwapTokenOption[];\n onOpenSourcePicker: () => void;\n routeStatus?: \"loading\" | \"insufficient\";\n routeMessage?: string;\n}) {\n const scrollRef = useRef(null);\n const isRouteLoading = routeStatus === \"loading\";\n const shouldShowSourceSummary = !isRouteLoading && fromTokens.length > 0;\n const shouldScroll = shouldShowSourceSummary && fromTokens.length > 3;\n const autoBadge = (\n \n AUTO\n \n );\n\n return (\n \n \n \n \n Pay With\n {shouldShowSourceSummary ? ` · ${fromTokens.length} assets` : \"\"}\n \n {autoBadge}\n \n {shouldShowSourceSummary && (\n \n Edit tokens\n \n )}\n \n\n {isRouteLoading ? (\n <>\n \n \n \n Calculating best route...\n \n \n ) : shouldShowSourceSummary ? (\n
\n \n {fromTokens.map((token, index) => (\n \n \n \n \n \n {token.symbol}\n \n \n {token.isUnified\n ? \"Unified balance\"\n : `on ${token.chainName || \"Unknown chain\"}`}\n \n
\n \n \n \n {formatToken(token.userAmount || token.balance)}{\" \"}\n {token.symbol}\n \n \n {formatUsd(token.userAmountUsd || token.balanceInFiat)}\n \n \n \n ))}\n \n {shouldScroll && (\n \n scrollRef.current?.scrollBy({ behavior: \"smooth\", top: 64 })\n }\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${border}`,\n borderRadius: \"999px\",\n bottom: \"4px\",\n boxShadow: \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n cursor: \"pointer\",\n display: \"flex\",\n height: \"22px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"22px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n ) : (\n \n Sources will be auto selected\n \n )}\n\n {routeStatus === \"insufficient\" && routeMessage && (\n \n \n {routeMessage}\n \n )}\n \n );\n}\n\nfunction BalanceSkeleton({\n height = \"16px\",\n width = \"72px\",\n}: {\n height?: string;\n width?: string;\n}) {\n return (\n \n );\n}\n\nexport function DepositIdleForm({\n amount,\n amountMode,\n onAmountChange,\n onAmountModeToggle,\n toToken,\n totalBalance,\n usdValue,\n tokenValue,\n fromTokens,\n onOpenSourcePicker,\n onSetPercent,\n routeStatus,\n routeMessage,\n isAmountReadOnly = false,\n isBalanceLoading = false,\n isCalculatingMax,\n calculatingPercent,\n isQuoteRefreshing,\n hideDestinationTokenDropdownIcon = false,\n showAutoBadge = true,\n isSourcePickerDisabled = false,\n isTokenPickerDisabled = false,\n onOpenTokenPicker,\n reserveSourceRows = false,\n}: DepositIdleFormProps) {\n const [selectedPercent, setSelectedPercent] = useState(null);\n const [pendingPercent, setPendingPercent] = useState(null);\n const [isAmountFocused, setIsAmountFocused] = useState(false);\n\n React.useEffect(() => {\n if (!isCalculatingMax) setPendingPercent(null);\n }, [isCalculatingMax]);\n\n React.useEffect(() => {\n setSelectedPercent(null);\n }, [toToken?.contractAddress, toToken?.chainId]);\n\n const handlePercentSelect = (pct: number) => {\n setSelectedPercent(pct);\n setPendingPercent(pct);\n onSetPercent(pct);\n };\n\n const handleInput = (e: React.ChangeEvent) => {\n if (isAmountReadOnly) return;\n setSelectedPercent(null);\n onAmountChange(\n sanitizeAmountInput(\n e.target.value,\n isUsdMode\n ? MAX_AMOUNT_DISPLAY_DECIMALS\n : getTokenInputDecimals(toToken),\n ),\n );\n };\n const isUsdMode = amountMode === \"usd\";\n const amountDisplayValue = isAmountFocused\n ? amount\n : formatAmountInputDisplay(amount);\n const showTokenPickerDropdownIcon =\n Boolean(onOpenTokenPicker) &&\n !isTokenPickerDisabled &&\n !hideDestinationTokenDropdownIcon;\n const activePendingPercent =\n calculatingPercent ?? (isCalculatingMax ? pendingPercent : null);\n const isMaxCalculating = Boolean(\n isCalculatingMax && activePendingPercent === 100,\n );\n const destinationBalanceLabel = isUsdMode\n ? formatUsdBalanceLabel(toToken?.balanceInFiat)\n : formatSelectedTokenBalanceLabel(toToken) ||\n `0 ${toToken?.symbol || \"\"}`.trim();\n\n return (\n \n \n \n \n Deposit\n \n
\n \n Total Balance:\n \n \n {isBalanceLoading ? (\n \n ) : (\n `$${totalBalance}`\n )}\n \n
\n \n\n
\n \n \n {isMaxCalculating ? (\n \n ) : (\n <>\n {isUsdMode && amount && (\n \n $\n \n )}\n setIsAmountFocused(false)}\n onChange={handleInput}\n onFocus={() => setIsAmountFocused(true)}\n placeholder=\"0\"\n style={{\n background: \"transparent\",\n border: \"none\",\n boxSizing: \"border-box\",\n color: amount ? primary : \"var(--nexus-widget-text-tertiary, #C8C8C6)\",\n cursor: isAmountReadOnly ? \"default\" : \"text\",\n fontFamily:\n '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"36px\",\n fontWeight: 500,\n lineHeight: \"44px\",\n minWidth: 0,\n outline: \"none\",\n padding: 0,\n width: \"100%\",\n }}\n readOnly={isAmountReadOnly}\n type=\"text\"\n value={amountDisplayValue}\n />\n \n )}\n {isCalculatingMax && !isMaxCalculating && (\n \n )}\n
\n\n \n \n \n {toToken?.chainLogo && (\n \n )}\n \n \n {toToken?.symbol || \"Token\"}\n \n {showTokenPickerDropdownIcon && (\n \n )}\n \n \n\n \n \n \n {isUsdMode\n ? `≈ ${tokenValue || \"0\"} ${toToken?.symbol || \"\"} ↕`\n : `≈ $${usdValue || \"0\"} ↕`}\n \n \n\n \n \n Balance:\n \n \n {isBalanceLoading ? (\n \n ) : (\n destinationBalanceLabel\n )}\n \n \n \n\n \n \n \n\n \n \n );\n}\n", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport Decimal from \"decimal.js\";\nimport { AlertCircle, ChevronDown, Loader2 } from \"lucide-react\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport { useNexusWidgetThemeStyle } from \"../theme-context\";\nimport React, { useRef, useState } from \"react\";\nimport { PayWithSources as SharedPayWithSources } from \"./pay-with-sources\";\nimport { NEXUS_WIDGET_FAST_SPINNER_STYLE } from \"../theme\";\nimport {\n formatSelectedTokenBalanceLabel,\n formatUsdBalanceLabel,\n type SwapTokenOption,\n} from \"./swap-asset-selector\";\n\ninterface DepositIdleFormProps {\n amount: string;\n amountMode: \"token\" | \"usd\";\n calculatingPercent?: number | null;\n fromTokens: SwapTokenOption[];\n isAmountReadOnly?: boolean;\n isBalanceLoading?: boolean;\n isCalculatingMax?: boolean;\n isQuoteRefreshing?: boolean;\n isSourcePickerDisabled?: boolean;\n isTokenPickerDisabled?: boolean;\n hideDestinationTokenDropdownIcon?: boolean;\n onAmountChange: (val: string) => void;\n onAmountModeToggle: () => void;\n onOpenSourcePicker: () => void;\n onOpenTokenPicker?: () => void;\n onSetPercent: (pct: number) => void;\n reserveSourceRows?: boolean;\n routeMessage?: string;\n routeStatus?: \"loading\" | \"insufficient\";\n showAutoBadge?: boolean;\n tokenValue: string;\n toToken?: SwapTokenOption;\n totalBalance: string;\n usdValue: string;\n}\n\nconst uiFont = '\"Geist\", system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\n\nconst formatToken = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst formatUsd = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n return `$${amount.toDecimalPlaces(2).toFixed()}`;\n};\n\nconst MAX_AMOUNT_DISPLAY_DECIMALS = 8;\nconst getTokenInputDecimals = (token?: Pick) => {\n const decimals = Number(token?.decimals);\n return Number.isFinite(decimals) && decimals >= 0 ? Math.floor(decimals) : 18;\n};\n\nconst formatAmountInputDisplay = (value: string) => {\n if (!value) return \"\";\n try {\n return new Decimal(value)\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n } catch {\n return value;\n }\n};\n\nconst sanitizeAmountInput = (raw: string, maxDecimals: number) => {\n let next = raw.replaceAll(/[^0-9.]/g, \"\");\n const parts = next.split(\".\");\n if (parts.length > 2) next = parts[0] + \".\" + parts.slice(1).join(\"\");\n const [integerPart, decimalPart] = next.split(\".\");\n if (decimalPart !== undefined) {\n next = `${integerPart}.${decimalPart.slice(0, Math.max(0, maxDecimals))}`;\n }\n if (next === \".\") next = \"0.\";\n return next;\n};\n\nfunction TokenLogo({\n src,\n label,\n size = 30,\n fontSize = 12,\n style,\n}: {\n src?: string;\n label?: string;\n size?: number;\n fontSize?: number;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n React.useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction SourceLogoPair({ token }: { token: SwapTokenOption }) {\n return (\n
\n \n {token.chainLogo && (\n \n )}\n
\n );\n}\n\nfunction ExactOutPercentButtons({\n visible,\n onSelect,\n selectedPercent,\n}: {\n visible: boolean;\n onSelect: (pct: number) => void;\n selectedPercent: number | null;\n}) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [focusedPercent, setFocusedPercent] = useState(null);\n\n React.useEffect(() => {\n if (!visible) setFocusedPercent(null);\n }, [visible]);\n\n return (\n \n {[25, 50, 75, 100].map((pct) => {\n const isMax = pct === 100;\n const isFocused = focusedPercent === pct;\n return (\n {\n e.stopPropagation();\n onSelect(pct);\n }}\n onBlur={() => setFocusedPercent(null)}\n onFocus={() => setFocusedPercent(pct)}\n style={{\n alignItems: \"center\",\n backgroundColor: isFocused ? \"var(--nexus-widget-primary-soft, #E8F0FF)\" : \"var(--nexus-widget-surface-raised, #F4F4F3)\",\n border: \"none\",\n borderRadius: \"8px\",\n boxSizing: \"border-box\",\n color: isFocused ? brand : \"var(--nexus-widget-text, #363635)\",\n cursor: \"pointer\",\n display: \"flex\",\n flex: \"1 1 0%\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"12px\",\n fontWeight: 500,\n justifyContent: \"center\",\n lineHeight: \"20px\",\n minWidth: 0,\n paddingBlock: \"5px\",\n paddingInline: \"10px\",\n }}\n type=\"button\"\n >\n {isMax ? \"MAX\" : `${pct}%`}\n \n );\n })}\n \n );\n}\n\nfunction SkeletonRow() {\n return (\n \n \n \n \n );\n}\n\nfunction PayWithSources({\n fromTokens,\n onOpenSourcePicker,\n routeStatus,\n routeMessage,\n}: {\n fromTokens: SwapTokenOption[];\n onOpenSourcePicker: () => void;\n routeStatus?: \"loading\" | \"insufficient\";\n routeMessage?: string;\n}) {\n const scrollRef = useRef(null);\n const isRouteLoading = routeStatus === \"loading\";\n const shouldShowSourceSummary = !isRouteLoading && fromTokens.length > 0;\n const shouldScroll = shouldShowSourceSummary && fromTokens.length > 3;\n const autoBadge = (\n \n AUTO\n \n );\n\n return (\n \n \n \n \n Pay With\n {shouldShowSourceSummary ? ` · ${fromTokens.length} assets` : \"\"}\n \n {autoBadge}\n \n {shouldShowSourceSummary && (\n \n Edit tokens\n \n )}\n \n\n {isRouteLoading ? (\n <>\n \n \n \n Calculating best route...\n \n \n ) : shouldShowSourceSummary ? (\n
\n \n {fromTokens.map((token, index) => (\n \n \n \n \n \n {token.symbol}\n \n \n {token.isUnified\n ? \"Unified balance\"\n : `on ${token.chainName || \"Unknown chain\"}`}\n \n
\n \n \n \n {formatToken(token.userAmount || token.balance)}{\" \"}\n {token.symbol}\n \n \n {formatUsd(token.userAmountUsd || token.balanceInFiat)}\n \n \n \n ))}\n \n {shouldScroll && (\n \n scrollRef.current?.scrollBy({ behavior: \"smooth\", top: 64 })\n }\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${border}`,\n borderRadius: \"999px\",\n bottom: \"4px\",\n boxShadow: \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n cursor: \"pointer\",\n display: \"flex\",\n height: \"22px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"22px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n ) : (\n \n Sources will be auto selected\n \n )}\n\n {routeStatus === \"insufficient\" && routeMessage && (\n \n \n {routeMessage}\n \n )}\n \n );\n}\n\nfunction BalanceSkeleton({\n height = \"16px\",\n width = \"72px\",\n}: {\n height?: string;\n width?: string;\n}) {\n return (\n \n );\n}\n\nexport function DepositIdleForm({\n amount,\n amountMode,\n onAmountChange,\n onAmountModeToggle,\n toToken,\n totalBalance,\n usdValue,\n tokenValue,\n fromTokens,\n onOpenSourcePicker,\n onSetPercent,\n routeStatus,\n routeMessage,\n isAmountReadOnly = false,\n isBalanceLoading = false,\n isCalculatingMax,\n calculatingPercent,\n isQuoteRefreshing,\n hideDestinationTokenDropdownIcon = false,\n showAutoBadge = true,\n isSourcePickerDisabled = false,\n isTokenPickerDisabled = false,\n onOpenTokenPicker,\n reserveSourceRows = false,\n}: DepositIdleFormProps) {\n const [selectedPercent, setSelectedPercent] = useState(null);\n const [pendingPercent, setPendingPercent] = useState(null);\n const [isAmountFocused, setIsAmountFocused] = useState(false);\n\n React.useEffect(() => {\n if (!isCalculatingMax) setPendingPercent(null);\n }, [isCalculatingMax]);\n\n React.useEffect(() => {\n setSelectedPercent(null);\n }, [toToken?.contractAddress, toToken?.chainId]);\n\n const handlePercentSelect = (pct: number) => {\n setSelectedPercent(pct);\n setPendingPercent(pct);\n onSetPercent(pct);\n };\n\n const handleInput = (e: React.ChangeEvent) => {\n if (isAmountReadOnly) return;\n setSelectedPercent(null);\n onAmountChange(\n sanitizeAmountInput(\n e.target.value,\n isUsdMode\n ? MAX_AMOUNT_DISPLAY_DECIMALS\n : getTokenInputDecimals(toToken),\n ),\n );\n };\n const isUsdMode = amountMode === \"usd\";\n const amountDisplayValue = isAmountFocused\n ? amount\n : formatAmountInputDisplay(amount);\n const showTokenPickerDropdownIcon =\n Boolean(onOpenTokenPicker) &&\n !isTokenPickerDisabled &&\n !hideDestinationTokenDropdownIcon;\n const activePendingPercent =\n calculatingPercent ?? (isCalculatingMax ? pendingPercent : null);\n const isMaxCalculating = Boolean(\n isCalculatingMax && activePendingPercent === 100,\n );\n const destinationBalanceLabel = isUsdMode\n ? formatUsdBalanceLabel(toToken?.balanceInFiat)\n : formatSelectedTokenBalanceLabel(toToken) ||\n `0 ${toToken?.symbol || \"\"}`.trim();\n\n return (\n \n \n \n \n Deposit\n \n
\n \n Total Balance:\n \n \n {isBalanceLoading ? (\n \n ) : (\n `$${totalBalance}`\n )}\n \n
\n \n\n
\n \n \n {isMaxCalculating ? (\n \n ) : (\n <>\n {isUsdMode && amount && (\n \n $\n \n )}\n setIsAmountFocused(false)}\n onChange={handleInput}\n onFocus={() => setIsAmountFocused(true)}\n placeholder=\"0\"\n style={{\n background: \"transparent\",\n border: \"none\",\n boxSizing: \"border-box\",\n color: amount ? primary : \"var(--nexus-widget-text-tertiary, #C8C8C6)\",\n cursor: isAmountReadOnly ? \"default\" : \"text\",\n fontFamily:\n '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"36px\",\n fontWeight: 500,\n lineHeight: \"44px\",\n minWidth: 0,\n outline: \"none\",\n padding: 0,\n width: \"100%\",\n }}\n readOnly={isAmountReadOnly}\n type=\"text\"\n value={amountDisplayValue}\n />\n \n )}\n {isCalculatingMax && !isMaxCalculating && (\n \n )}\n
\n\n \n \n \n {toToken?.chainLogo && (\n \n )}\n \n \n {toToken?.symbol || \"Token\"}\n \n {showTokenPickerDropdownIcon && (\n \n )}\n \n \n\n \n \n \n {isUsdMode\n ? `≈ ${tokenValue || \"0\"} ${toToken?.symbol || \"\"} ↕`\n : `≈ $${usdValue || \"0\"} ↕`}\n \n \n\n \n \n Balance:\n \n \n {isBalanceLoading ? (\n \n ) : (\n destinationBalanceLabel\n )}\n \n \n \n\n \n \n \n\n \n \n );\n}\n", "type": "registry:component", "target": "components/nexus/components/deposit-idle-form.tsx" }, + { + "path": "registry/avail-widgets/nexus-widget/components/deposit-onramp-flow.tsx", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport Decimal from \"decimal.js\";\nimport {\n Check,\n ChevronDown,\n CreditCard,\n ExternalLink,\n Info,\n Landmark,\n Loader2,\n Search,\n Smartphone,\n X,\n} from \"lucide-react\";\nimport React from \"react\";\nimport {\n encodeFunctionData,\n erc20Abi,\n formatUnits,\n isAddress,\n parseUnits,\n zeroAddress,\n type Address,\n type Hex,\n type WalletClient,\n} from \"viem\";\nimport { NEXUS_WIDGET_FAST_SPINNER_STYLE, nexusWidgetTheme } from \"../theme\";\nimport type { NexusWidgetDepositOpportunityConfig } from \"../types\";\nimport type { SwapTokenOption } from \"./swap-asset-selector\";\nimport {\n useOnrampWallet,\n type GetOnrampWalletProvider,\n} from \"../utils/use-onramp-wallet\";\nimport { CHAIN_METADATA } from \"../../common\";\nimport {\n getOnrampRemainingAmount,\n onrampDelay,\n waitForOnrampReceipt,\n getNormalizedOnrampState,\n isOnrampTerminalState,\n logOnramp,\n getOnrampBaseUrl,\n ONRAMP_CLIENT_HEADER,\n mergeOnrampSession,\n normalizeOnrampSession,\n startOnrampPolling,\n type OnrampSessionResponse,\n} from \"../utils/onramp-session\";\nimport type { OnrampHistoryUpdate } from \"../utils/onramp-history\";\n\ntype OnrampCryptoCurrency = {\n chainCode?: string;\n chainId: number | string;\n contract?: string;\n currencyCode: string;\n decimals?: number;\n name?: string;\n symbolUrl?: string;\n token?: string;\n};\n\ntype OnrampProviderLogo = {\n dark?: string;\n darkShort?: string;\n light?: string;\n lightShort?: string;\n};\n\ntype OnrampProviderMetadata = {\n logo?: OnrampProviderLogo;\n name: string;\n provider: string;\n};\n\ntype OnrampCountry = {\n countryCode: string;\n flagUrl?: string;\n name: string;\n subdivisions?: unknown[];\n};\n\ntype OnrampFiatMetadata = {\n currencyCode: string;\n decimals?: number;\n flagUrl?: string;\n name?: string;\n symbolUrl?: string;\n};\n\ntype OnrampFiatCurrency =\n | string\n | {\n code?: string;\n currencyCode?: string;\n decimals?: number;\n flagUrl?: string;\n name?: string;\n symbol?: string;\n symbolUrl?: string;\n };\n\ntype OnrampFiatCurrencyOption = {\n currencyCode: string;\n decimals?: number;\n flagUrl?: string;\n name?: string;\n symbol?: string;\n symbolUrl?: string;\n};\n\ntype OnrampPaymentMethodLogo =\n | {\n dark?: string;\n light?: string;\n }\n | string;\n\ntype OnrampOptionsResponse = {\n countries?: OnrampCountry[];\n fiatCurrencyMetadata?: OnrampFiatMetadata[];\n paymentMethodMetadata?: OnrampPaymentMethod[];\n paymentMethods?: OnrampPaymentMethod[];\n providers?: OnrampProviderMetadata[];\n selection?: {\n countryCode: string;\n cryptoCurrencies?: OnrampCryptoCurrency[];\n defaultFiat?: string;\n defaultPaymentMethods?: string[];\n fiatCurrencies?: OnrampFiatCurrency[];\n fiatCurrencyMetadata?: OnrampFiatMetadata[];\n paymentMethods?: OnrampPaymentMethod[];\n } | null;\n};\n\ntype IpCountryResponse = {\n country?: string;\n ip?: string;\n};\n\ntype OnrampErrorResponse = {\n code?: string;\n errorId?: string;\n message?: string;\n subcode?: string;\n};\n\ntype OnrampPaymentMethod = {\n description?: string;\n duration?: string;\n estimatedDuration?: string;\n estimatedTime?: string;\n headlessSupported?: boolean;\n limits?: {\n currencyCode?: string;\n max?: string;\n min?: string;\n };\n logo?: OnrampPaymentMethodLogo;\n method: string;\n name?: string;\n subtitle?: string;\n type?: string;\n};\n\ntype OnrampRoute = {\n paymentMethods?: OnrampPaymentMethod[];\n provider: string;\n};\n\ntype OnrampRoutesResponse = {\n routes?: OnrampRoute[];\n};\n\ntype OnrampProviderOption = {\n destinationAmount?: string;\n paymentMethod?: OnrampPaymentMethod;\n paymentMethodType?: string;\n provider: string;\n quote?: OnrampQuote;\n route?: OnrampRoute;\n};\n\ntype OnrampQuote = {\n destinationAmount: string;\n destinationCurrencyCode: string;\n fees?: {\n network?: string;\n partner?: string;\n provider?: string;\n total?: string;\n };\n lowKyc?: boolean;\n paymentMethodType: string;\n provider: string;\n rampScore?: number;\n sourceAmount: string;\n sourceCurrencyCode: string;\n};\n\ntype OnrampQuoteResponse = {\n quotes?: OnrampQuote[];\n};\n\ntype OnrampCacheRecord = {\n expiresAt: number;\n value: T;\n};\n\ntype OnrampBlockedRequest = {\n key: string;\n message: string;\n};\n\ntype OnrampDepositExecutionState = {\n amount?: string;\n error?: string;\n explorerUrl?: string;\n status: \"idle\" | \"running\" | \"success\" | \"failed\";\n step?: \"swapping_gas\" | \"depositing\";\n txHash?: Hex;\n};\n\ntype OnrampNexusSDK = {\n chainList?: {\n getChainByID?: (chainId: number) =>\n | {\n blockExplorers?: {\n default?: {\n url?: string;\n };\n };\n nativeCurrency?: {\n decimals?: number;\n name?: string;\n symbol?: string;\n };\n rpcUrls?: {\n default?: {\n http?: string[];\n };\n };\n }\n | null\n | undefined;\n };\n swapWithExactOut?: (input: any, options?: any) => Promise;\n [key: string]: any;\n};\n\nexport type OnrampGasShortfallInfo = {\n estimatedGasUnits: bigint;\n gasPriceWei: bigint;\n hasApproval: boolean;\n isErc20: boolean;\n isShortfall: boolean;\n requiredGasEth: string;\n requiredGasWei: bigint;\n shortfallAmountEth: string;\n shortfallAmountRaw: bigint;\n userGasBalanceEth: string;\n userGasBalanceWei: bigint;\n};\n\ntype OnrampSheet =\n | \"country\"\n | \"currency\"\n | \"destination\"\n | \"fees\"\n | \"method\"\n | \"partner\"\n | null;\n\ninterface DepositOnrampFlowProps {\n baseUrl?: string;\n getWalletProvider: GetOnrampWalletProvider;\n walletConnected: boolean;\n destinationTokens?: SwapTokenOption[];\n onConnectWallet: () => void | Promise;\n onError?: (message: string) => void;\n onSelectDestinationToken?: (token: SwapTokenOption) => void;\n onSessionStateChange?: (state: string | null) => void;\n onSessionUpdate?: (update: OnrampHistoryUpdate) => void;\n nexusSDK?: OnrampNexusSDK | null;\n ownerAddress?: string;\n opportunity?: NexusWidgetDepositOpportunityConfig;\n primaryButtonForeground: string;\n toToken?: SwapTokenOption;\n walletClient?: WalletClient | null;\n}\n\nconst ONRAMP_RETURN_PATH = \"/onramp/complete\";\nconst ONRAMP_IP_COUNTRY_URL = \"https://api.country.is/\";\nconst ONRAMP_IP_API_URL = \"http://ip-api.com/json\";\nconst ONRAMP_IPAPI_CO_URL = \"https://ipapi.co/json/\";\nconst ONRAMP_CLOUDFLARE_META_URL = \"https://speed.cloudflare.com/meta\";\nconst ONRAMP_DISCONNECTED_QUOTE_WALLET_ADDRESS =\n \"0xd733d48f2a7f57d4559f98ae07f87dab595e3523\" as Address;\nconst ONRAMP_OPTIONS_CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;\nconst ONRAMP_COUNTRY_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\nconst ONRAMP_USER_COUNTRY_CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;\nconst ONRAMP_COUNTRY_CACHE_KEY = \"nexus-widgets:onramp:country:v1\";\nconst ONRAMP_USER_COUNTRY_CACHE_KEY = \"nexus-widgets:onramp:user-country:v1\";\nconst ONRAMP_OPTIONS_CACHE_KEY_PREFIX = \"nexus-widgets:onramp:options:v1\";\nconst ONRAMP_SANDBOX_FALLBACK_COUNTRY = \"FR\";\nconst ONRAMP_PRODUCTION_FALLBACK_COUNTRY = \"US\";\nconst QUOTE_REFRESH_SECONDS = 60;\nconst QUOTE_REFRESH_MS = QUOTE_REFRESH_SECONDS * 1000;\nconst ONRAMP_SESSION_POLL_MS = 3000;\nconst ONRAMP_CALLBACK_MESSAGE_TYPE = \"nexus-widgets:onramp:session\";\nconst ONRAMP_CALLBACK_SUCCESS_MESSAGE = \"nexus-onramp-success\";\nconst ONRAMP_CALLBACK_SUCCESS_ACK_MESSAGE = \"nexus-onramp-success-received\";\nconst ONRAMP_CALLBACK_CHANNEL = \"nexus-widgets:onramp\";\nconst ONRAMP_CALLBACK_STORAGE_KEY = \"nexus-widgets:onramp:session\";\nconst ONRAMP_PROGRESS_ARTWORK_URL =\n \"https://files.availproject.org/nexus-elements/nexus-one/progress-grid.gif\";\nconst ONRAMP_SHEET_EDGE_OFFSET = \"-16px\";\nconst ONRAMP_GENERIC_QUOTE_ERROR_MESSAGE =\n \"We are facing some issues at the moment, try again later\";\nconst theme = nexusWidgetTheme;\nconst brand = \"var(--foreground-brand)\";\n\nconst panelStyle: React.CSSProperties = {\n backgroundColor: theme.colors.surface,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: \"12px\",\n boxShadow: theme.shadows.card,\n boxSizing: \"border-box\",\n overflow: \"hidden\",\n width: \"100%\",\n};\n\nconst sectionLabelStyle: React.CSSProperties = {\n color: theme.colors.textSubtle,\n flexShrink: 0,\n fontFamily: theme.fonts.sans,\n fontSize: \"12px\",\n fontWeight: 600,\n letterSpacing: \"0.08em\",\n lineHeight: \"15px\",\n textTransform: \"uppercase\",\n};\n\nconst compactTitleStyle: React.CSSProperties = {\n color: theme.colors.textStrong,\n fontFamily: theme.fonts.display,\n fontSize: \"18px\",\n fontWeight: 500,\n letterSpacing: \"0\",\n lineHeight: \"23px\",\n};\n\nconst compactBodyStyle: React.CSSProperties = {\n color: theme.colors.textSubtle,\n fontFamily: theme.fonts.sans,\n fontSize: \"13px\",\n lineHeight: \"18px\",\n};\n\nfunction OnrampQuoteCountdownIcon({ progress }: { progress: number }) {\n const radius = 7;\n const circumference = 2 * Math.PI * radius;\n const clampedProgress = Math.max(0, Math.min(1, progress));\n\n return (\n \n \n \n \n );\n}\n\nconst parseDecimal = (value: unknown) => {\n if (value === null || value === undefined || value === \"\") return undefined;\n if (Decimal.isDecimal(value)) return value;\n const cleaned = String(value).replace(/[^0-9.-]/g, \"\");\n if (!cleaned || cleaned === \"-\" || cleaned === \".\" || cleaned === \"-.\") {\n return undefined;\n }\n try {\n const parsed = new Decimal(cleaned);\n return parsed.isFinite() ? parsed : undefined;\n } catch {\n return undefined;\n }\n};\n\nconst normalizeAmountInput = (raw: string) => {\n let next = raw.replaceAll(/[^0-9.]/g, \"\");\n const parts = next.split(\".\");\n if (parts.length > 2) next = parts[0] + \".\" + parts.slice(1).join(\"\");\n const [integerPart, decimalPart] = next.split(\".\");\n if (decimalPart !== undefined) {\n next = `${integerPart}.${decimalPart.slice(0, 2)}`;\n }\n if (next === \".\") next = \"0.\";\n return next;\n};\n\nconst formatNumberDisplay = (value: unknown, maxDecimals = 2) => {\n const parsed = parseDecimal(value) ?? new Decimal(0);\n const fixed = parsed\n .toDecimalPlaces(maxDecimals, Decimal.ROUND_DOWN)\n .toFixed();\n const [intPart, decPart] = fixed.split(\".\");\n const formattedInt = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n return decPart !== undefined ? `${formattedInt}.${decPart}` : formattedInt;\n};\n\nconst formatPlainNumberDisplay = (value: unknown, maxDecimals = 6) => {\n const parsed = parseDecimal(value);\n if (!parsed || parsed.isZero()) return \"0\";\n return parsed.toDecimalPlaces(maxDecimals, Decimal.ROUND_DOWN).toFixed();\n};\n\nconst ONRAMP_FOREX_RATES_CACHE_KEY = \"nexus_onramp_forex_rates_usd\";\nconst ONRAMP_FOREX_RATES_TTL_MS = 60 * 60 * 1000; // 1 hour\n\nconst fetchOnrampForexRates = async (\n signal?: AbortSignal,\n): Promise> => {\n const cached = readOnrampCache>(\n ONRAMP_FOREX_RATES_CACHE_KEY,\n );\n if (cached && typeof cached === \"object\" && Object.keys(cached).length > 0) {\n return cached;\n }\n try {\n logOnramp(\"forex.request\");\n const res = await fetch(\"https://open.er-api.com/v6/latest/USD\", {\n signal: signal\n ? AbortSignal.any([signal, AbortSignal.timeout(15_000)])\n : AbortSignal.timeout(15_000),\n });\n if (res.ok) {\n const data = await res.json();\n if (data?.rates && typeof data.rates === \"object\") {\n const rates = data.rates as Record;\n writeOnrampCache(\n ONRAMP_FOREX_RATES_CACHE_KEY,\n rates,\n ONRAMP_FOREX_RATES_TTL_MS,\n );\n return rates;\n }\n }\n } catch (e) {\n logOnramp(\"Failed to fetch onramp forex rates\", e);\n }\n return {};\n};\n\nconst FIAT_EXCLUSIVE_SYMBOLS: Record = {\n CNY: \"¥\",\n EUR: \"€\",\n GBP: \"£\",\n ILS: \"₪\",\n INR: \"₹\",\n JPY: \"¥\",\n KPW: \"₩\",\n KRW: \"₩\",\n NGN: \"₦\",\n PHP: \"₱\",\n RUB: \"₽\",\n THB: \"฿\",\n TRY: \"₺\",\n USD: \"$\",\n VND: \"₫\",\n};\n\nconst formatCurrencyAmount = (\n value: unknown,\n currencyCode?: string,\n maxDecimals = 2,\n) => {\n const code = (currencyCode ?? \"\").toUpperCase();\n const symbol = code ? FIAT_EXCLUSIVE_SYMBOLS[code] : undefined;\n const formatted = formatNumberDisplay(value, maxDecimals);\n if (symbol) {\n return `${symbol}${formatted}`;\n }\n return code ? `${formatted} ${code}` : formatted;\n};\n\nconst formatUsdDisplay = (value: unknown) => {\n const parsed = parseDecimal(value) ?? new Decimal(0);\n if (parsed.gt(0) && parsed.lt(0.01)) return \"<$0.01\";\n return `$${formatNumberDisplay(parsed, 2)}`;\n};\n\nconst getIntlCurrencyName = (currencyCode?: string) => {\n if (!currencyCode) return \"\";\n try {\n return (\n new Intl.DisplayNames([\"en\"], { type: \"currency\" }).of(\n currencyCode.toUpperCase(),\n ) ?? currencyCode\n );\n } catch {\n return currencyCode;\n }\n};\n\nconst getIntlCurrencySymbol = (currencyCode?: string) => {\n if (!currencyCode) return undefined;\n const normalized = currencyCode.toUpperCase();\n if (FIAT_EXCLUSIVE_SYMBOLS[normalized]) {\n return FIAT_EXCLUSIVE_SYMBOLS[normalized];\n }\n try {\n return new Intl.NumberFormat(\"en\", {\n currency: normalized,\n currencyDisplay: \"narrowSymbol\",\n style: \"currency\",\n })\n .formatToParts(0)\n .find((part) => part.type === \"currency\")?.value;\n } catch {\n return undefined;\n }\n};\n\nconst getFiatCurrencyCode = (currency: OnrampFiatCurrency) =>\n (typeof currency === \"string\"\n ? currency\n : (currency.currencyCode ?? currency.code ?? \"\")\n ).toUpperCase();\n\nconst getFiatCurrencyName = (\n currencyCode?: string,\n currency?: OnrampFiatCurrencyOption,\n) => currency?.name ?? getIntlCurrencyName(currencyCode);\n\nconst getCountryByCode = (\n countries: OnrampCountry[] | undefined,\n countryCode?: string,\n) =>\n countries?.find(\n (country) =>\n country.countryCode.toUpperCase() === countryCode?.toUpperCase(),\n );\n\nconst isCountryInOptionsList = (\n options: OnrampOptionsResponse,\n countryCode: string,\n) => {\n if (!options.countries?.length) return true;\n return Boolean(getCountryByCode(options.countries, countryCode));\n};\n\nconst getCountryFlagUrl = (\n countries: OnrampCountry[] | undefined,\n countryCode?: string,\n) => {\n const normalizedCountryCode = countryCode?.toUpperCase();\n if (!normalizedCountryCode) return undefined;\n return getCountryByCode(countries, normalizedCountryCode)?.flagUrl;\n};\n\nconst onrampProviderMetadataCache = new Map();\n\nconst cacheOnrampProviders = (providers?: OnrampProviderMetadata[]) => {\n if (!providers?.length) return;\n for (const provider of providers) {\n if (!provider?.provider) continue;\n onrampProviderMetadataCache.set(provider.provider.toUpperCase(), provider);\n }\n};\n\nconst getProviderMetadata = (provider?: string) => {\n if (!provider) return undefined;\n return onrampProviderMetadataCache.get(provider.toUpperCase());\n};\n\nconst onrampFiatMetadataCache = new Map();\n\nconst cacheOnrampFiatMetadata = (metadata?: OnrampFiatMetadata[]) => {\n if (!metadata?.length) return;\n for (const item of metadata) {\n if (!item?.currencyCode) continue;\n onrampFiatMetadataCache.set(item.currencyCode.toUpperCase(), item);\n }\n};\n\nconst getFiatMetadata = (currencyCode?: string) => {\n if (!currencyCode) return undefined;\n return onrampFiatMetadataCache.get(currencyCode.toUpperCase());\n};\n\nconst getCurrencyLogoUrl = (\n currencyCode?: string,\n currency?: OnrampFiatCurrencyOption,\n) => {\n if (currency?.symbolUrl || currency?.flagUrl) {\n return currency.symbolUrl ?? currency.flagUrl;\n }\n if (!currencyCode) return undefined;\n const meta = getFiatMetadata(currencyCode);\n return meta?.symbolUrl ?? meta?.flagUrl;\n};\n\nconst onrampPaymentMethodMetadataCache = new Map();\n\nconst cacheOnrampPaymentMethods = (methods?: OnrampPaymentMethod[]) => {\n if (!methods?.length) return;\n for (const method of methods) {\n if (!method?.method) continue;\n const key = method.method.toUpperCase();\n const existing = onrampPaymentMethodMetadataCache.get(key);\n onrampPaymentMethodMetadataCache.set(key, {\n ...existing,\n ...method,\n });\n }\n};\n\nconst getPaymentMethodMetadata = (method?: string) => {\n if (!method) return undefined;\n return onrampPaymentMethodMetadataCache.get(method.toUpperCase());\n};\n\nconst getPaymentMethodLogoUrl = (\n method?: string,\n logo?: OnrampPaymentMethodLogo,\n isDark?: boolean,\n) => {\n const resolvedLogo = logo ?? getPaymentMethodMetadata(method)?.logo;\n if (!resolvedLogo) return undefined;\n if (typeof resolvedLogo === \"string\") return resolvedLogo;\n if (isDark) {\n return resolvedLogo.dark || resolvedLogo.light;\n }\n return resolvedLogo.light || resolvedLogo.dark;\n};\n\nconst getFiatCurrencyOptions = (\n options: OnrampOptionsResponse | null,\n): OnrampFiatCurrencyOption[] => {\n const selection = options?.selection;\n const fiatMetadataList =\n selection?.fiatCurrencyMetadata ?? options?.fiatCurrencyMetadata;\n cacheOnrampFiatMetadata(fiatMetadataList);\n if (options?.providers) {\n cacheOnrampProviders(options.providers);\n }\n const paymentMethodList =\n selection?.paymentMethods ??\n options?.paymentMethods ??\n options?.paymentMethodMetadata;\n if (paymentMethodList) {\n cacheOnrampPaymentMethods(paymentMethodList);\n }\n\n const byCode = new Map();\n\n for (const currency of selection?.fiatCurrencies ?? []) {\n const currencyCode = getFiatCurrencyCode(currency);\n if (!currencyCode || byCode.has(currencyCode)) continue;\n const meta =\n getFiatMetadata(currencyCode) ??\n (typeof currency === \"object\" ? currency : undefined);\n\n const logoUrl =\n typeof currency === \"object\"\n ? (currency.symbolUrl ??\n currency.flagUrl ??\n meta?.symbolUrl ??\n meta?.flagUrl)\n : (meta?.symbolUrl ??\n meta?.flagUrl ??\n getCountryFlagUrl(options?.countries, currencyCode.slice(0, 2)));\n\n byCode.set(currencyCode, {\n currencyCode,\n decimals:\n typeof currency === \"object\"\n ? (currency.decimals ?? meta?.decimals)\n : meta?.decimals,\n flagUrl: logoUrl,\n name:\n typeof currency === \"object\"\n ? (currency.name ?? meta?.name ?? getIntlCurrencyName(currencyCode))\n : (meta?.name ?? getIntlCurrencyName(currencyCode)),\n symbol:\n typeof currency === \"object\"\n ? (currency.symbol ?? getIntlCurrencySymbol(currencyCode))\n : getIntlCurrencySymbol(currencyCode),\n symbolUrl: logoUrl,\n });\n }\n\n const defaultFiat = selection?.defaultFiat?.toUpperCase();\n if (defaultFiat && !byCode.has(defaultFiat)) {\n const meta = getFiatMetadata(defaultFiat);\n const logoUrl =\n meta?.symbolUrl ??\n meta?.flagUrl ??\n getCountryFlagUrl(options?.countries, defaultFiat.slice(0, 2));\n byCode.set(defaultFiat, {\n currencyCode: defaultFiat,\n decimals: meta?.decimals,\n flagUrl: logoUrl,\n name: meta?.name ?? getIntlCurrencyName(defaultFiat),\n symbol: getIntlCurrencySymbol(defaultFiat),\n symbolUrl: logoUrl,\n });\n }\n\n return Array.from(byCode.values());\n};\n\nconst readOnrampCache = (key: string) => {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = window.localStorage.getItem(key);\n if (!raw) return null;\n const cached = JSON.parse(raw) as OnrampCacheRecord;\n if (!cached?.expiresAt || cached.expiresAt <= Date.now()) {\n window.localStorage.removeItem(key);\n return null;\n }\n return cached.value;\n } catch {\n return null;\n }\n};\n\nconst writeOnrampCache = (key: string, value: T, ttlMs: number) => {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(\n key,\n JSON.stringify({\n expiresAt: Date.now() + ttlMs,\n value,\n } satisfies OnrampCacheRecord),\n );\n } catch {\n // Cache failures should not affect the onramp flow.\n }\n};\n\nconst getOnrampOptionsCacheKey = (baseUrl: string, countryCode: string) =>\n `${ONRAMP_OPTIONS_CACHE_KEY_PREFIX}:${baseUrl}:${countryCode.toUpperCase()}`;\n\nconst readCachedOnrampOptions = (baseUrl: string, countryCode: string) =>\n readOnrampCache(\n getOnrampOptionsCacheKey(baseUrl, countryCode),\n );\n\nconst writeCachedOnrampOptions = (\n baseUrl: string,\n countryCode: string,\n options: OnrampOptionsResponse,\n) => {\n writeOnrampCache(\n getOnrampOptionsCacheKey(baseUrl, countryCode),\n options,\n ONRAMP_OPTIONS_CACHE_TTL_MS,\n );\n};\n\nconst getOnrampReturnUrl = () =>\n (typeof process !== \"undefined\" &&\n process.env.NEXT_PUBLIC_NEXUS_ONRAMP_RETURN_URL?.trim()) ||\n (typeof window !== \"undefined\"\n ? `${window.location.origin}${ONRAMP_RETURN_PATH}`\n : ONRAMP_RETURN_PATH);\nconst getOnrampRuntimeEnvironment = (_baseUrl: string) => {\n const explicit =\n typeof process !== \"undefined\"\n ? process.env.NEXT_PUBLIC_NEXUS_ONRAMP_ENV?.trim().toLowerCase()\n : undefined;\n // Mainnet is a production Nexus deployment, not evidence of a Meld sandbox.\n return explicit === \"sandbox\" || explicit === \"testnet\"\n ? \"sandbox\"\n : \"production\";\n};\n\nconst getUnsupportedCountryFallbackCode = (baseUrl: string) => {\n const environment = getOnrampRuntimeEnvironment(baseUrl);\n return environment === \"production\"\n ? ONRAMP_PRODUCTION_FALLBACK_COUNTRY\n : ONRAMP_SANDBOX_FALLBACK_COUNTRY;\n};\n\nconst isValidCountryCode = (code?: string): code is string =>\n Boolean(code && /^[A-Za-z]{2}$/.test(code));\n\nconst fetchCountryIs = async (signal?: AbortSignal): Promise => {\n const response = await fetch(ONRAMP_IP_COUNTRY_URL, {\n signal,\n headers: { Accept: \"application/json\" },\n method: \"GET\",\n });\n if (!response.ok) throw new Error(\"country.is failed\");\n const data = (await response.json()) as IpCountryResponse;\n const country = data.country?.trim()?.toUpperCase();\n if (isValidCountryCode(country)) return country;\n throw new Error(\"Invalid country code from country.is\");\n};\n\nconst fetchIpApi = async (signal?: AbortSignal): Promise => {\n const response = await fetch(ONRAMP_IP_API_URL, {\n signal,\n headers: { Accept: \"application/json\" },\n method: \"GET\",\n });\n if (!response.ok) throw new Error(\"ip-api.com failed\");\n const data = (await response.json()) as {\n countryCode?: string;\n country?: string;\n };\n const country = (data.countryCode ?? data.country)?.trim()?.toUpperCase();\n if (isValidCountryCode(country)) return country;\n throw new Error(\"Invalid country code from ip-api.com\");\n};\n\nconst fetchIpapiCo = async (signal?: AbortSignal): Promise => {\n const response = await fetch(ONRAMP_IPAPI_CO_URL, {\n signal,\n headers: { Accept: \"application/json\" },\n method: \"GET\",\n });\n if (!response.ok) throw new Error(\"ipapi.co failed\");\n const data = (await response.json()) as {\n country?: string;\n country_code?: string;\n };\n const country = (data.country_code ?? data.country)?.trim()?.toUpperCase();\n if (isValidCountryCode(country)) return country;\n throw new Error(\"Invalid country code from ipapi.co\");\n};\n\nconst fetchCloudflareSpeedMeta = async (\n signal?: AbortSignal,\n): Promise => {\n const response = await fetch(ONRAMP_CLOUDFLARE_META_URL, {\n signal,\n method: \"GET\",\n });\n if (!response.ok) throw new Error(\"cloudflare meta failed\");\n const text = await response.text();\n const data = JSON.parse(text) as { country?: string };\n const country = data.country?.trim()?.toUpperCase();\n if (isValidCountryCode(country)) return country;\n throw new Error(\"Invalid country code from cloudflare\");\n};\n\nconst getIpCountryCode = async (signal?: AbortSignal) => {\n const timeoutSignal = AbortSignal.timeout(15_000);\n const combinedSignal = signal\n ? AbortSignal.any([signal, timeoutSignal])\n : timeoutSignal;\n\n try {\n const country = await Promise.any([\n fetchCountryIs(combinedSignal),\n fetchIpApi(combinedSignal),\n fetchIpapiCo(combinedSignal),\n fetchCloudflareSpeedMeta(combinedSignal),\n ]);\n return country;\n } catch {\n return \"\";\n }\n};\n\nconst getLocalCountryCode = () => {\n if (typeof navigator === \"undefined\") return \"\";\n const locales = [...(navigator.languages ?? []), navigator.language].filter(\n Boolean,\n );\n for (const locale of locales) {\n const countryCode = locale.match(/[-_]([A-Za-z]{2})$/)?.[1]?.toUpperCase();\n if (countryCode) return countryCode;\n }\n return \"\";\n};\n\nconst resolveOnrampCountryCode = async (signal?: AbortSignal) => {\n const userSelected = readOnrampCache(ONRAMP_USER_COUNTRY_CACHE_KEY);\n if (userSelected) return userSelected;\n\n const cached = readOnrampCache(ONRAMP_COUNTRY_CACHE_KEY);\n if (cached) return cached;\n\n const resolved =\n (await getIpCountryCode(signal)) || getLocalCountryCode() || \"US\";\n writeOnrampCache(\n ONRAMP_COUNTRY_CACHE_KEY,\n resolved,\n ONRAMP_COUNTRY_CACHE_TTL_MS,\n );\n return resolved;\n};\n\nconst getDefaultFiatCurrencyCode = (options: OnrampOptionsResponse | null) => {\n const currencies = getFiatCurrencyOptions(options);\n const defaultFiat = options?.selection?.defaultFiat?.toUpperCase();\n if (\n defaultFiat &&\n currencies.some((currency) => currency.currencyCode === defaultFiat)\n ) {\n return defaultFiat;\n }\n return currencies[0]?.currencyCode ?? \"\";\n};\n\nconst getMethodLabel = (method?: string, customName?: string) => {\n if (customName) return customName;\n const meta = getPaymentMethodMetadata(method);\n if (meta?.name) return meta.name;\n switch ((method ?? \"\").toUpperCase()) {\n case \"APPLE_PAY\":\n return \"Apple Pay\";\n case \"GOOGLE_PAY\":\n return \"Google Pay\";\n case \"UPI\":\n return \"UPI\";\n case \"IMPS\":\n return \"IMPS\";\n case \"CREDIT_DEBIT_CARD\":\n case \"CARD\":\n return \"Credit / Debit Cards\";\n case \"BANK_TRANSFER\":\n case \"NEFT\":\n case \"RTGS\":\n case \"AR_BANK_TRANSFER\":\n case \"NG_BANK_TRANSFER\":\n return \"Bank Transfer\";\n case \"SEPA\":\n return \"SEPA\";\n case \"REVOLUT_PAY\":\n case \"REVOLUT\":\n return \"Revolut Pay\";\n case \"MOBILE_MONEY\":\n return \"Mobile Money\";\n case \"BINANCE_P2P\":\n return \"Binance P2P\";\n case \"PAYMAYA\":\n return \"PayMaya\";\n case \"GCASH\":\n return \"GCash\";\n case \"GRABPAY\":\n return \"GrabPay\";\n case \"SPEI\":\n return \"SPEI\";\n case \"MX_CASH\":\n return \"Cash\";\n case \"ROBINHOOD_BUYING_POWER\":\n case \"ROBINHOOD\":\n return \"Robinhood\";\n default:\n return method\n ? method\n .split(\"_\")\n .filter(Boolean)\n .map(\n (part) =>\n part.charAt(0).toUpperCase() + part.slice(1).toLowerCase(),\n )\n .join(\" \")\n : \"Payment method\";\n }\n};\n\nconst getMethodSubtitle = (method?: OnrampPaymentMethod) => {\n const subtitle =\n method?.subtitle ??\n method?.description ??\n method?.estimatedTime ??\n method?.estimatedDuration ??\n method?.duration;\n return typeof subtitle === \"string\" && subtitle.trim()\n ? subtitle.trim()\n : undefined;\n};\n\nconst getProviderLabel = (provider?: string) => {\n if (!provider) return \"Payment partner\";\n const meta = getProviderMetadata(provider);\n if (meta?.name) return meta.name;\n return provider\n .split(/[_\\s-]+/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())\n .join(\" \");\n};\n\nconst getProviderInitials = (provider?: string) => {\n const label = getProviderLabel(provider);\n const parts = label.split(/\\s+/).filter(Boolean);\n if (parts.length <= 1) return label.slice(0, 2).toUpperCase();\n return `${parts[0]?.[0] ?? \"\"}${parts[1]?.[0] ?? \"\"}`.toUpperCase();\n};\n\nclass OnrampRequestError extends Error {\n code?: string;\n errorId?: string;\n rawMessage?: string;\n status: number;\n subcode?: string;\n\n constructor({\n code,\n errorId,\n message,\n rawMessage,\n status,\n subcode,\n }: {\n code?: string;\n errorId?: string;\n message: string;\n rawMessage?: string;\n status: number;\n subcode?: string;\n }) {\n super(message);\n this.name = \"OnrampRequestError\";\n this.code = code;\n this.errorId = errorId;\n this.rawMessage = rawMessage;\n this.status = status;\n this.subcode = subcode;\n }\n}\n\nconst getErrorMessage = (error: unknown) => {\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n return \"Unable to continue with local currency.\";\n};\n\nconst getOnrampErrorSignature = (error: OnrampRequestError) =>\n [error.code, error.subcode, error.rawMessage, error.message]\n .filter(Boolean)\n .join(\" \")\n .toUpperCase();\n\nconst isUnsupportedOnrampDestinationError = (error: unknown) => {\n if (!(error instanceof OnrampRequestError)) return false;\n const signature = getOnrampErrorSignature(error);\n return (\n signature.includes(\"ASSET_NOT_SUPPORTED\") ||\n signature.includes(\"CURRENCY_NOT_SUPPORTED\") ||\n signature.includes(\"TOKEN_NOT_SUPPORTED\") ||\n signature.includes(\"TOKEN UNSUPPORTED\") ||\n signature.includes(\"UNSUPPORTED_DESTINATION\") ||\n signature.includes(\"UNSUPPORTED TOKEN\") ||\n signature.includes(\"DESTINATION ASSET IS NOT SUPPORTED\") ||\n signature.includes(\"DESTINATIONCHAINID IS INVALID\") ||\n signature.includes(\"DESTINATIONTOKEN IS INVALID\")\n );\n};\n\nconst isOnrampConfigError = (error: unknown) => {\n if (!(error instanceof OnrampRequestError)) return false;\n const signature = getOnrampErrorSignature(error);\n return (\n signature.includes(\"CONFIG\") ||\n signature.includes(\"CONFIGURATION\") ||\n signature.includes(\"NOT CONFIGURED\") ||\n signature.includes(\"NO ROUTE\") ||\n (signature.includes(\"ROUTE\") && signature.includes(\"UNAVAILABLE\"))\n );\n};\n\nconst isTerminalOnrampRateError = (error: unknown) =>\n isUnsupportedOnrampDestinationError(error) || isOnrampConfigError(error);\n\nconst getOnrampRequestErrorMessage = (\n error: unknown,\n context?: {\n countryCode?: string;\n sourceCurrencyCode?: string;\n token?: SwapTokenOption;\n },\n) => {\n if (isTerminalOnrampRateError(error)) {\n const tokenLabel = context?.token?.symbol\n ? `${context.token.symbol}${\n context.token.chainName ? ` on ${context.token.chainName}` : \"\"\n }`\n : \"this token\";\n const localeLabel = [context?.countryCode, context?.sourceCurrencyCode]\n .filter(Boolean)\n .join(\" / \");\n return `Local currency deposits are not available for ${tokenLabel}${\n localeLabel ? ` with ${localeLabel}` : \"\"\n }. Choose another deposit token or pay with wallet.`;\n }\n\n return getErrorMessage(error);\n};\n\nconst getOnrampRateRequestKey = ({\n countryCode,\n destinationChainId,\n destinationCurrencyCode,\n destinationToken,\n sourceCurrencyCode,\n}: {\n countryCode?: string;\n destinationChainId?: string;\n destinationCurrencyCode?: string;\n destinationToken?: string;\n sourceCurrencyCode?: string;\n}) =>\n [\n countryCode?.toUpperCase() ?? \"\",\n sourceCurrencyCode?.toUpperCase() ?? \"\",\n destinationCurrencyCode?.toUpperCase() ?? \"\",\n destinationChainId ?? \"\",\n destinationToken?.toLowerCase() ?? \"\",\n ].join(\"|\");\n\nconst isOnrampProcessingState = (state?: string | null) => {\n const normalized = getNormalizedOnrampState(state);\n return [\n \"PROCESSING\",\n \"SETTLING\",\n \"PENDING\",\n \"PENDING CREATED\",\n \"PENDING_CREATED\",\n \"TWO_FA_REQUIRED\",\n \"TWO_FA_PROVIDED\",\n \"ERROR\",\n \"ACCEPTED\",\n \"AUTHORIZED\",\n \"PARTIALLY_SETTLED\",\n ].includes(normalized);\n};\n\nconst ONRAMP_DEPOSIT_PROCESSING_STATES = new Set([\n \"COMPLETING_DEPOSIT\",\n \"DEPOSIT_PROCESSING\",\n \"DEPOSITING\",\n \"SWAPPING_GAS\",\n]);\n\nconst ONRAMP_DEPOSIT_SUCCESS_STATES = new Set([\n \"DEPOSIT_COMPLETE\",\n \"DEPOSIT_SUCCESS\",\n \"DEPOSITED\",\n]);\n\nconst ONRAMP_DEPOSIT_FAILED_STATES = new Set([\n \"DEPOSIT_ATTENTION\",\n \"DEPOSIT_FAILED\",\n \"DEPOSIT_REQUIRES_ATTENTION\",\n]);\n\nconst isOnrampDepositProcessingState = (state?: string | null) =>\n ONRAMP_DEPOSIT_PROCESSING_STATES.has(getNormalizedOnrampState(state));\n\nconst isOnrampDepositSuccessState = (state?: string | null) =>\n ONRAMP_DEPOSIT_SUCCESS_STATES.has(getNormalizedOnrampState(state));\n\nconst isOnrampDepositFailedState = (state?: string | null) =>\n ONRAMP_DEPOSIT_FAILED_STATES.has(getNormalizedOnrampState(state));\n\nconst isNativeAddress = (address?: string) => {\n const lower = address?.toLowerCase();\n return (\n lower === zeroAddress ||\n lower === \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\"\n );\n};\n\nconst isPositiveGasLimit = (value: unknown): value is bigint => {\n try {\n return BigInt(value as bigint) > BigInt(0);\n } catch {\n return false;\n }\n};\n\nconst FALLBACK_CHAIN_RPCS: Record = {\n 1: \"https://ethereum-rpc.publicnode.com\",\n 10: \"https://mainnet.optimism.io\",\n 56: \"https://bsc-dataseed.binance.org\",\n 137: \"https://polygon-rpc.com\",\n 8453: \"https://mainnet.base.org\",\n 42161: \"https://arb1.arbitrum.io/rpc\",\n 43114: \"https://api.avax.network/ext/bc/C/rpc\",\n 534352: \"https://rpc.scroll.io\",\n 11155111: \"https://rpc.sepolia.org\",\n 84532: \"https://sepolia.base.org\",\n 421614: \"https://sepolia-rollup.arbitrum.io/rpc\",\n 11155420: \"https://sepolia.optimism.io\",\n 80002: \"https://rpc-amoy.polygon.technology\",\n};\n\nconst getChainRpcUrl = (\n chainId?: number,\n nexusSDK?: OnrampNexusSDK | null,\n): string | undefined => {\n if (!chainId) return undefined;\n const sdkRpc =\n nexusSDK?.chainList?.getChainByID?.(chainId)?.rpcUrls?.default?.http?.[0];\n if (sdkRpc) return sdkRpc;\n const metaRpc = CHAIN_METADATA[chainId]?.rpcUrls?.[0];\n if (metaRpc) return metaRpc;\n return FALLBACK_CHAIN_RPCS[chainId];\n};\n\nconst makeJsonRpcCall = async (\n rpcUrl: string,\n method: string,\n params: any[] = [],\n signal?: AbortSignal,\n): Promise => {\n logOnramp(\"rpc.request\", { method });\n const response = await fetch(rpcUrl, {\n signal: signal\n ? AbortSignal.any([signal, AbortSignal.timeout(15_000)])\n : AbortSignal.timeout(15_000),\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n id: Date.now(),\n jsonrpc: \"2.0\",\n method,\n params,\n }),\n });\n if (!response.ok) {\n throw new Error(`RPC request failed with status ${response.status}`);\n }\n const json = await response.json();\n if (json.error) {\n throw new Error(json.error.message || \"RPC call error\");\n }\n logOnramp(\"rpc.response\", { method, result: json.result });\n return json.result as T;\n};\n\nconst fetchDestinationGasPriceWei = async (\n chainId: number,\n walletClient?: WalletClient | null,\n nexusSDK?: OnrampNexusSDK | null,\n): Promise => {\n const rpcUrl = getChainRpcUrl(chainId, nexusSDK);\n const useWallet = walletClient?.chain?.id === chainId;\n\n // 1. Try Type-2 EIP-1559 fee calculation\n try {\n let maxPriorityFeeHex: string | null = null;\n let baseFeeHex: string | null = null;\n\n if (useWallet && walletClient) {\n try {\n maxPriorityFeeHex = (await walletClient.request({\n method: \"eth_maxPriorityFeePerGas\",\n } as any)) as string;\n } catch {}\n try {\n const block = (await walletClient.request({\n method: \"eth_getBlockByNumber\",\n params: [\"latest\", false],\n } as any)) as { baseFeePerGas?: string } | null;\n baseFeeHex = block?.baseFeePerGas ?? null;\n } catch {}\n }\n\n if (!maxPriorityFeeHex && rpcUrl) {\n try {\n maxPriorityFeeHex = await makeJsonRpcCall(\n rpcUrl,\n \"eth_maxPriorityFeePerGas\",\n );\n } catch {}\n }\n\n if (!baseFeeHex && rpcUrl) {\n try {\n const block = await makeJsonRpcCall<{ baseFeePerGas?: string }>(\n rpcUrl,\n \"eth_getBlockByNumber\",\n [\"latest\", false],\n );\n baseFeeHex = block?.baseFeePerGas ?? null;\n } catch {}\n }\n\n const priorityFee = maxPriorityFeeHex\n ? BigInt(maxPriorityFeeHex)\n : BigInt(0);\n const baseFee = baseFeeHex ? BigInt(baseFeeHex) : BigInt(0);\n\n if (priorityFee > BigInt(0) && baseFee > BigInt(0)) {\n return baseFee * BigInt(2) + priorityFee;\n }\n if (priorityFee > BigInt(0)) {\n return priorityFee;\n }\n } catch (err) {\n logOnramp(\n \"Error fetching type 2 gas fee, falling back to eth_gasPrice\",\n err,\n );\n }\n\n // 2. Fallback to eth_gasPrice\n try {\n if (useWallet && walletClient) {\n const gasPriceHex = (await walletClient.request({\n method: \"eth_gasPrice\",\n } as any)) as string;\n if (gasPriceHex) {\n const parsed = BigInt(gasPriceHex);\n if (parsed > BigInt(0)) return parsed;\n }\n }\n\n if (rpcUrl) {\n const gasPriceHex = await makeJsonRpcCall(rpcUrl, \"eth_gasPrice\");\n if (gasPriceHex) {\n const parsed = BigInt(gasPriceHex);\n if (parsed > BigInt(0)) return parsed;\n }\n }\n } catch (err) {\n logOnramp(\"Error fetching eth_gasPrice\", err);\n }\n\n // 3. Fallback default (1 Gwei)\n throw new Error(\n \"Unable to fetch the destination gas price. Retry Deposit when the RPC is available.\",\n );\n};\n\nconst fetchUserNativeGasBalanceWei = async (\n account: Address,\n chainId: number,\n walletClient?: WalletClient | null,\n nexusSDK?: OnrampNexusSDK | null,\n): Promise => {\n const rpcUrl = getChainRpcUrl(chainId, nexusSDK);\n const useWallet = walletClient?.chain?.id === chainId;\n\n try {\n if (useWallet && walletClient) {\n const balanceHex = (await walletClient.request({\n method: \"eth_getBalance\",\n params: [account, \"latest\"],\n } as any)) as string;\n if (balanceHex) return BigInt(balanceHex);\n }\n\n if (rpcUrl) {\n const balanceHex = await makeJsonRpcCall(\n rpcUrl,\n \"eth_getBalance\",\n [account, \"latest\"],\n );\n if (balanceHex) return BigInt(balanceHex);\n }\n } catch (err) {\n logOnramp(\"Failed to fetch user native gas balance\", err);\n }\n\n throw new Error(\n \"Unable to fetch the wallet gas balance. Retry Deposit when the RPC is available.\",\n );\n};\n\nconst isErc20Token = (token?: SwapTokenOption, chainId?: number) => {\n if (!token?.contractAddress) return false;\n if (isNativeAddress(token.contractAddress)) return false;\n const effectiveChainId = token.chainId ?? chainId;\n const nativeSymbol = effectiveChainId\n ? CHAIN_METADATA[effectiveChainId]?.nativeCurrency?.symbol?.toUpperCase()\n : undefined;\n if (\n nativeSymbol &&\n token.symbol?.toUpperCase() === nativeSymbol &&\n isNativeAddress(token.contractAddress)\n ) {\n return false;\n }\n return true;\n};\n\nconst getOnrampChainIdNumber = (chainId?: number | string) => {\n if (typeof chainId === \"number\") return chainId;\n const match = chainId?.match(/\\d+$/);\n return match ? Number(match[0]) : undefined;\n};\n\nconst getOnrampCurrencyAddress = (currency?: OnrampCryptoCurrency) =>\n currency?.contract ?? currency?.token;\n\nconst getOnrampCryptoCurrency = (\n options: OnrampOptionsResponse | null,\n token?: SwapTokenOption,\n) => {\n if (!token?.chainId || !token.contractAddress) return undefined;\n\n const targetAddress = token.contractAddress.toLowerCase();\n return options?.selection?.cryptoCurrencies?.find((currency) => {\n if (getOnrampChainIdNumber(currency.chainId) !== token.chainId)\n return false;\n const address = getOnrampCurrencyAddress(currency)?.toLowerCase();\n if (!address) return false;\n return (\n address === targetAddress ||\n (isNativeAddress(address) && isNativeAddress(targetAddress))\n );\n });\n};\n\nconst getDestinationRequestDetails = (\n options: OnrampOptionsResponse | null,\n token?: SwapTokenOption,\n) => {\n const matched = getOnrampCryptoCurrency(options, token);\n return {\n destinationChainId: token?.chainId ? `EVM_${token.chainId}` : undefined,\n destinationCurrencyCode:\n matched?.currencyCode ?? token?.symbol?.toUpperCase() ?? \"\",\n destinationToken: token?.contractAddress,\n };\n};\n\nconst getRawTokenAmount = (amount: unknown, decimals: number) => {\n const parsed = parseDecimal(amount);\n if (!parsed?.gt(0)) return null;\n return parseUnits(\n parsed.toDecimalPlaces(decimals, Decimal.ROUND_DOWN).toFixed(),\n decimals,\n );\n};\n\nconst isMatchingOnrampToken = (\n token: SwapTokenOption,\n chainId: number,\n tokenAddress: string,\n) => {\n if (token.chainId !== chainId) return false;\n const candidateAddress = token.contractAddress?.toLowerCase();\n const targetAddress = tokenAddress.toLowerCase();\n return (\n candidateAddress === targetAddress ||\n (isNativeAddress(candidateAddress) && isNativeAddress(targetAddress))\n );\n};\n\nconst getTransactionExplorerUrl = (chainId?: number, txHash?: string) => {\n const baseUrl = getExplorerBaseUrl(chainId);\n return baseUrl && txHash ? `${baseUrl}${txHash}` : undefined;\n};\n\nconst getNexusChainTransactionExplorerUrl = (\n nexusSDK: OnrampNexusSDK | null | undefined,\n chainId?: number,\n txHash?: string,\n) => {\n if (!chainId || !txHash) return undefined;\n try {\n const baseUrl =\n nexusSDK?.chainList?.getChainByID?.(chainId)?.blockExplorers?.default\n ?.url;\n if (baseUrl) return `${baseUrl.replace(/\\/+$/, \"\")}/tx/${txHash}`;\n } catch {\n return getTransactionExplorerUrl(chainId, txHash);\n }\n return getTransactionExplorerUrl(chainId, txHash);\n};\n\nconst waitForWalletTransactionSuccess = async (\n walletClient: WalletClient,\n txHash: Hex,\n chainId: number,\n nexusSDK: OnrampNexusSDK | null | undefined,\n signal: AbortSignal,\n) => {\n const rpcUrl = getChainRpcUrl(chainId, nexusSDK);\n logOnramp(\"wallet.receipt.wait\", { chainId, txHash });\n const receipt = await waitForOnrampReceipt(async () => {\n const receipt = rpcUrl\n ? await makeJsonRpcCall<{ status?: string } | null>(\n rpcUrl,\n \"eth_getTransactionReceipt\",\n [txHash],\n signal,\n )\n : ((await walletClient.request({\n method: \"eth_getTransactionReceipt\",\n params: [txHash],\n } as any)) as { status?: string } | null);\n logOnramp(\"wallet.receipt.poll\", { chainId, txHash, receipt });\n return receipt;\n }, signal);\n logOnramp(\"wallet.receipt.confirmed\", { chainId, txHash, receipt });\n return receipt;\n};\n\nconst getOnrampTokenKey = (token?: SwapTokenOption) => {\n if (!token?.chainId || !token.contractAddress) return \"\";\n return `${token.chainId}:${token.contractAddress.toLowerCase()}`;\n};\n\nconst isSameOnrampToken = (left?: SwapTokenOption, right?: SwapTokenOption) =>\n Boolean(\n left && right && getOnrampTokenKey(left) === getOnrampTokenKey(right),\n );\n\nconst sortQuotes = (quotes: OnrampQuote[]) =>\n [...quotes].sort((a, b) => {\n const aAmount = parseDecimal(a.destinationAmount) ?? new Decimal(0);\n const bAmount = parseDecimal(b.destinationAmount) ?? new Decimal(0);\n const destinationDelta = bAmount.cmp(aAmount);\n if (destinationDelta !== 0) return destinationDelta;\n const scoreDelta = (b.rampScore ?? 0) - (a.rampScore ?? 0);\n return scoreDelta;\n });\n\nconst matchesSearch = (query: string, values: Array) => {\n const normalizedQuery = query.trim().toLowerCase();\n if (!normalizedQuery) return true;\n return values.some((value) =>\n (value ?? \"\").toLowerCase().includes(normalizedQuery),\n );\n};\n\nconst createIdempotencyKey = () => {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(16).slice(2)}`;\n};\n\nconst openOnrampProviderWindow = () => {\n if (typeof window === \"undefined\") return null;\n const providerWindow = window.open(\"about:blank\", \"_blank\");\n if (!providerWindow) return null;\n providerWindow.document.title = \"Opening payment provider\";\n providerWindow.document.body.style.fontFamily =\n \"system-ui, -apple-system, BlinkMacSystemFont, sans-serif\";\n providerWindow.document.body.style.margin = \"0\";\n providerWindow.document.body.style.display = \"grid\";\n providerWindow.document.body.style.minHeight = \"100vh\";\n providerWindow.document.body.style.placeItems = \"center\";\n providerWindow.document.body.textContent = \"Opening payment provider...\";\n return providerWindow;\n};\n\ntype OnrampCallbackPayload = {\n session?: OnrampSessionResponse;\n sessionId: string;\n state?: string;\n timestamp?: number;\n type: string;\n};\n\ndeclare global {\n interface Window {\n setRampSessionId?: (sessionId: string) => void;\n }\n}\n\nconst isOnrampCallbackPayload = (\n payload: unknown,\n): payload is OnrampCallbackPayload => {\n if (!payload || typeof payload !== \"object\") return false;\n const candidate = payload as Partial;\n return (\n candidate.type === ONRAMP_CALLBACK_MESSAGE_TYPE &&\n typeof candidate.sessionId === \"string\" &&\n candidate.sessionId.length > 0\n );\n};\n\nconst fetchOnrampJson = async (\n baseUrl: string,\n path: string,\n init?: RequestInit,\n) => {\n const requestId = createIdempotencyKey();\n const startedAt = Date.now();\n const controller = new AbortController();\n const abort = () => controller.abort();\n init?.signal?.addEventListener(\"abort\", abort, { once: true });\n if (init?.signal?.aborted) controller.abort();\n const timeout = setTimeout(abort, 20_000);\n logOnramp(\"api.request\", {\n requestId,\n path,\n method: init?.method ?? \"GET\",\n request: typeof init?.body === \"string\" ? JSON.parse(init.body) : undefined,\n });\n try {\n const response = await fetch(`${baseUrl}${path}`, {\n ...init,\n cache: \"no-store\",\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-nexus-client\": ONRAMP_CLIENT_HEADER,\n ...(init?.headers ?? {}),\n },\n });\n const text = await response.text();\n let data: any = {};\n try {\n data = text ? JSON.parse(text) : {};\n } catch {\n data = text ? { message: text } : {};\n }\n\n logOnramp(\"api.response\", {\n requestId,\n path,\n httpStatus: response.status,\n durationMs: Date.now() - startedAt,\n response: path.includes(\"/sessions\")\n ? normalizeOnrampSession(data)\n : undefined,\n quoteCount: data.quotes?.length,\n routeCount: data.routes?.length,\n countryCount: data.countries?.length,\n cacheStatus:\n response.headers.get(\"x-cache\") ??\n response.headers.get(\"cf-cache-status\"),\n age: response.headers.get(\"age\"),\n });\n if (!response.ok) {\n const errorData = data as OnrampErrorResponse;\n const baseMessage =\n typeof errorData?.message === \"string\"\n ? errorData.message\n : `Onramp request failed (${response.status})`;\n const details = [errorData?.subcode, errorData?.errorId]\n .filter(Boolean)\n .join(\" · \");\n const message = details ? `${baseMessage} (${details})` : baseMessage;\n throw new OnrampRequestError({\n code: errorData?.code,\n errorId: errorData?.errorId,\n message,\n rawMessage: baseMessage,\n status: response.status,\n subcode: errorData?.subcode,\n });\n }\n\n return data as T;\n } catch (error) {\n logOnramp(\"api.error\", {\n requestId,\n path,\n durationMs: Date.now() - startedAt,\n aborted: controller.signal.aborted,\n error,\n });\n throw error;\n } finally {\n clearTimeout(timeout);\n init?.signal?.removeEventListener(\"abort\", abort);\n }\n};\n\nfunction TokenLogo({\n label,\n size = 30,\n src,\n}: {\n label?: string;\n size?: number;\n src?: string;\n}) {\n const [failed, setFailed] = React.useState(!src);\n\n React.useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: theme.colors.surface,\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").slice(0, 2).toUpperCase()}\n \n );\n}\n\nfunction TokenLogoPair({ token }: { token?: SwapTokenOption }) {\n return (\n \n \n {token?.chainLogo && (\n \n \n \n )}\n \n );\n}\n\nfunction CurrencyMark({\n code,\n currency,\n}: {\n code?: string;\n currency?: OnrampFiatCurrencyOption;\n}) {\n const displayCode = currency?.currencyCode ?? code;\n const imageUrl = getCurrencyLogoUrl(displayCode, currency);\n\n if (imageUrl) {\n return ;\n }\n\n return (\n \n {(currency?.symbol ?? displayCode ?? \"?\").slice(0, 3).toUpperCase()}\n \n );\n}\n\nfunction CountryMark({\n countryCode,\n flagUrl,\n size = 20,\n}: {\n countryCode?: string;\n flagUrl?: string;\n size?: number;\n}) {\n const code = countryCode?.toUpperCase() ?? \"\";\n const [failed, setFailed] = React.useState(!flagUrl);\n\n React.useEffect(() => {\n setFailed(!flagUrl);\n }, [flagUrl]);\n\n if (!failed && flagUrl) {\n return (\n setFailed(true)}\n src={flagUrl}\n style={{\n backgroundColor: theme.colors.surface,\n borderRadius: \"999px\",\n display: \"block\",\n flexShrink: 0,\n height: `${size}px`,\n objectFit: \"cover\",\n width: `${size}px`,\n }}\n />\n );\n }\n\n return (\n \n {(code || \"?\").slice(0, 2).toUpperCase()}\n \n );\n}\n\n\nconst useIsDarkMode = () => {\n const [isDark, setIsDark] = React.useState(false);\n\n React.useEffect(() => {\n if (typeof window === \"undefined\" || typeof document === \"undefined\")\n return;\n\n const checkDark = () => {\n const root =\n typeof document !== \"undefined\" ? document.documentElement : undefined;\n const body = typeof document !== \"undefined\" ? document.body : undefined;\n const isDarkClass = Boolean(\n root?.classList?.contains(\"dark\") || body?.classList?.contains(\"dark\"),\n );\n const isDataThemeDark = root?.getAttribute?.(\"data-theme\") === \"dark\";\n const prefersDark =\n typeof window.matchMedia === \"function\"\n ? Boolean(window.matchMedia(\"(prefers-color-scheme: dark)\")?.matches)\n : false;\n return Boolean(isDarkClass || isDataThemeDark || prefersDark);\n };\n\n setIsDark(checkDark());\n\n const mediaQuery =\n typeof window.matchMedia === \"function\"\n ? window.matchMedia(\"(prefers-color-scheme: dark)\")\n : undefined;\n const handleMediaChange = () => setIsDark(checkDark());\n mediaQuery?.addEventListener?.(\"change\", handleMediaChange);\n\n const root =\n typeof document !== \"undefined\" ? document.documentElement : undefined;\n let observer: MutationObserver | undefined;\n if (root && typeof MutationObserver !== \"undefined\") {\n observer = new MutationObserver(() => {\n setIsDark(checkDark());\n });\n observer.observe(root, {\n attributes: true,\n attributeFilter: [\"class\", \"data-theme\"],\n });\n }\n\n return () => {\n mediaQuery?.removeEventListener?.(\"change\", handleMediaChange);\n observer?.disconnect();\n };\n }, []);\n\n return isDark;\n};\n\nfunction ProviderMark({ provider }: { provider?: string }) {\n const isDark = useIsDarkMode();\n const meta = getProviderMetadata(provider);\n const logo = meta?.logo;\n const [failed, setFailed] = React.useState(false);\n\n const logoUrl = React.useMemo(() => {\n if (!logo) return undefined;\n if (isDark) {\n return logo.darkShort || logo.lightShort || logo.dark || logo.light;\n }\n return logo.lightShort || logo.darkShort || logo.light || logo.dark;\n }, [logo, isDark]);\n\n React.useEffect(() => {\n setFailed(false);\n }, [logoUrl]);\n\n if (logoUrl && !failed) {\n return (\n \n setFailed(true)}\n src={logoUrl}\n style={{\n height: \"100%\",\n objectFit: \"contain\",\n padding: \"3px\",\n width: \"100%\",\n }}\n />\n \n );\n }\n\n return (\n \n {getProviderInitials(provider)}\n \n );\n}\n\nconst PAYMENT_METHOD_LOGOS: Record = {\n APPLE_PAY: \"https://files.availproject.org/widgets/nexus/assets/applepay.svg\",\n BINANCE_P2P: \"https://files.availproject.org/widgets/nexus/assets/binance.png\",\n GCASH: \"https://files.availproject.org/widgets/nexus/assets/gcash.png\",\n GOOGLE_PAY: \"https://files.availproject.org/widgets/nexus/assets/googlepay.svg\",\n GRABPAY: \"https://files.availproject.org/widgets/nexus/assets/grabpay.svg\",\n IMPS: \"https://files.availproject.org/widgets/nexus/assets/imps.png\",\n PAYMAYA: \"https://files.availproject.org/widgets/nexus/assets/paymaya.svg\",\n REVOLUT: \"https://files.availproject.org/widgets/nexus/assets/revolut.svg\",\n REVOLUT_PAY: \"https://files.availproject.org/widgets/nexus/assets/revolut.svg\",\n ROBINHOOD: \"https://files.availproject.org/widgets/nexus/assets/robinhood.jpg\",\n ROBINHOOD_BUYING_POWER:\n \"https://files.availproject.org/widgets/nexus/assets/robinhood.jpg\",\n SEPA: \"https://files.availproject.org/widgets/nexus/assets/sepa.jpg\",\n UPI: \"https://files.availproject.org/widgets/nexus/assets/upi.png\",\n};\n\nconst PAYMENT_METHOD_LOGO_STYLES: Record = {\n GOOGLE_PAY: {\n padding: 0,\n transform: \"scale(1.35)\",\n },\n};\n\nfunction MethodMark({\n alt,\n logo,\n method,\n}: {\n alt?: string;\n logo?: OnrampPaymentMethodLogo;\n method?: string;\n}) {\n const isDark = useIsDarkMode();\n const normalized = (method ?? \"\").toUpperCase();\n const apiLogoUrl = getPaymentMethodLogoUrl(method, logo, isDark);\n const staticLogoUrl = PAYMENT_METHOD_LOGOS[normalized];\n const customLogoStyle = PAYMENT_METHOD_LOGO_STYLES[normalized];\n const [apiFailed, setApiFailed] = React.useState(false);\n const [staticFailed, setStaticFailed] = React.useState(false);\n\n React.useEffect(() => {\n setApiFailed(false);\n }, [apiLogoUrl]);\n\n React.useEffect(() => {\n setStaticFailed(false);\n }, [staticLogoUrl]);\n\n const candidateUrl =\n (!apiFailed && apiLogoUrl) || (!staticFailed && staticLogoUrl) || undefined;\n\n if (candidateUrl) {\n return (\n \n {\n if (candidateUrl === apiLogoUrl) {\n setApiFailed(true);\n } else {\n setStaticFailed(true);\n }\n }}\n src={candidateUrl}\n style={{\n maxHeight: \"100%\",\n maxWidth: \"100%\",\n objectFit: \"contain\",\n padding: \"4px\",\n ...(candidateUrl === staticLogoUrl ? customLogoStyle : undefined),\n }}\n />\n \n );\n }\n\n const icon =\n normalized === \"CREDIT_DEBIT_CARD\" ||\n normalized === \"CARD\" ||\n normalized.includes(\"CARD\") ? (\n \n ) : normalized.includes(\"BANK\") ||\n normalized === \"NEFT\" ||\n normalized === \"RTGS\" ||\n normalized === \"SPEI\" ? (\n \n ) : (\n \n );\n\n return (\n \n {icon}\n \n );\n}\n\nfunction SelectPill({\n children,\n disabled,\n onClick,\n}: {\n children: React.ReactNode;\n disabled?: boolean;\n onClick?: () => void;\n}) {\n return (\n \n {children}\n {!disabled && (\n \n )}\n \n );\n}\n\nfunction EditButton({\n disabled,\n onClick,\n}: {\n disabled?: boolean;\n onClick: () => void;\n}) {\n return (\n \n Edit\n \n );\n}\n\nfunction DetailRow({\n action,\n children,\n divider,\n label,\n}: {\n action?: React.ReactNode;\n children: React.ReactNode;\n divider?: boolean;\n label: string;\n}) {\n return (\n \n \n
{label}
\n {action}\n \n {children}\n \n );\n}\n\nfunction Sheet({\n children,\n onClose,\n title,\n}: {\n children: React.ReactNode;\n onClose: () => void;\n title: string;\n}) {\n return (\n \n \n \n \n
{title}
\n \n \n \n \n \n {children}\n \n \n \n );\n}\n\nfunction SheetSearchInput({\n onChange,\n placeholder,\n value,\n}: {\n onChange: (value: string) => void;\n placeholder: string;\n value: string;\n}) {\n const [focused, setFocused] = React.useState(false);\n return (\n \n \n setFocused(false)}\n onChange={(event) => onChange(event.target.value)}\n onFocus={() => setFocused(true)}\n placeholder={placeholder}\n style={{\n backgroundColor: \"transparent\",\n border: \"none\",\n boxSizing: \"border-box\",\n color: theme.colors.textStrong,\n flex: \"1 1 0%\",\n fontFamily: theme.fonts.sans,\n fontSize: \"14px\",\n height: \"100%\",\n lineHeight: \"18px\",\n minWidth: 0,\n outline: \"none\",\n padding: 0,\n }}\n value={value}\n />\n {value && (\n onChange(\"\")}\n style={{\n alignItems: \"center\",\n backgroundColor: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n display: \"flex\",\n flexShrink: 0,\n padding: \"2px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n );\n}\n\nfunction SelectRow({\n icon,\n onClick,\n primary,\n selected,\n subtitle,\n title,\n value,\n}: {\n icon: React.ReactNode;\n onClick: () => void;\n primary?: boolean;\n selected: boolean;\n subtitle?: string;\n title: string;\n value?: string;\n}) {\n return (\n \n {icon}\n \n \n \n {title}\n \n {primary && (\n \n Best rate\n \n )}\n \n {subtitle && (\n \n {subtitle}\n \n )}\n \n {value && (\n \n {value}\n \n )}\n \n {selected && (\n \n )}\n \n \n );\n}\n\nfunction EmptySheetMessage({ children }: { children: React.ReactNode }) {\n return (\n \n {children}\n \n );\n}\n\nfunction SkeletonBlock({\n borderRadius = \"8px\",\n height,\n width,\n}: {\n borderRadius?: string;\n height: string;\n width: string;\n}) {\n return (\n \n );\n}\n\nfunction QuoteDetailsSkeleton({ showFees = true }: { showFees?: boolean }) {\n return (\n
\n \n }\n label=\"Payment Method\"\n >\n
\n \n \n
\n \n\n \n }\n divider\n label=\"Payment Partner\"\n >\n
\n \n
\n \n \n
\n
\n \n\n {showFees && (\n \n
\n \n \n
\n
\n \n \n
\n
\n )}\n \n );\n}\n\nconst formatTokenAmountDisplay = (amount: unknown, symbol?: string) => {\n const suffix = symbol ? ` ${symbol}` : \"\";\n if (amount === null || amount === undefined || amount === \"\") {\n return suffix ? `--${suffix}` : \"--\";\n }\n return `${formatNumberDisplay(amount, 6)}${suffix}`;\n};\n\nconst getOnrampSessionSubtitle = (\n state: string | null | undefined,\n opportunity?: NexusWidgetDepositOpportunityConfig,\n) => {\n const normalized = getNormalizedOnrampState(state);\n if (isOnrampDepositSuccessState(normalized)) {\n return `The amount was deposited on ${getDepositTargetLabel(opportunity)}`;\n }\n if (isOnrampDepositFailedState(normalized)) {\n return \"The funds are in your wallet, but the deposit transaction could not be performed automatically.\";\n }\n if (isOnrampDepositProcessingState(normalized)) {\n return \"Usually takes 20 seconds\";\n }\n if (normalized === \"FAILED\") return \"The payment could not be completed\";\n if (normalized === \"CANCELLED\") return \"No payment was completed\";\n if (normalized === \"REFUNDED\") return \"The payment was refunded\";\n if (normalized === \"EXPIRED\") return \"Start a new payment to continue\";\n if (isOnrampProcessingState(normalized)) return \"Usually takes 2 - 5 min\";\n return \"The payment processor requires some information\";\n};\n\nconst getOnrampSummaryLabel = (\n state: string | null | undefined,\n provider?: string,\n) => {\n const partner = getProviderLabel(provider);\n const normalized = getNormalizedOnrampState(state);\n if (normalized === \"SETTLED\") return `Payment received from ${partner}`;\n if (normalized === \"FAILED\") return `Payment failed with ${partner}`;\n if (normalized === \"CANCELLED\") return `Payment cancelled with ${partner}`;\n if (normalized === \"REFUNDED\") return `Payment refunded by ${partner}`;\n if (normalized === \"EXPIRED\") return `Payment expired with ${partner}`;\n if (isOnrampProcessingState(normalized)) {\n return `Payment to be received by ${partner}`;\n }\n return `Payment to receive from ${partner}`;\n};\n\nconst getDepositTargetLabel = (\n opportunity?: NexusWidgetDepositOpportunityConfig,\n) =>\n opportunity?.title ||\n opportunity?.label ||\n opportunity?.protocol ||\n \"the selected market\";\n\nconst getDepositChainName = (\n opportunity?: NexusWidgetDepositOpportunityConfig,\n token?: SwapTokenOption,\n) =>\n token?.chainName ?? opportunity?.subtitle?.replace(/^on\\s+/i, \"\") ?? \"chain\";\n\nconst getExplorerBaseUrl = (chainId?: number) => {\n switch (chainId) {\n case 1:\n return \"https://etherscan.io/tx/\";\n case 10:\n return \"https://optimistic.etherscan.io/tx/\";\n case 56:\n return \"https://bscscan.com/tx/\";\n case 137:\n return \"https://polygonscan.com/tx/\";\n case 8453:\n return \"https://basescan.org/tx/\";\n case 42161:\n return \"https://arbiscan.io/tx/\";\n case 43114:\n return \"https://snowtrace.io/tx/\";\n default:\n return undefined;\n }\n};\n\nconst getOnrampExplorerUrl = (\n session: OnrampSessionResponse,\n token?: SwapTokenOption,\n) => {\n if (session.deposit?.explorerUrl) return session.deposit.explorerUrl;\n const txHash = session.deposit?.txHash;\n const baseUrl = getExplorerBaseUrl(token?.chainId);\n return txHash && baseUrl ? `${baseUrl}${txHash}` : undefined;\n};\n\nfunction OnrampStatusArtwork() {\n return (\n \n \n \n );\n}\n\nfunction SafeCloseNotice() {\n return (\n \n \n Keep this page open to finish your deposit\n \n );\n}\n\nfunction OnrampStatusButton({\n children,\n onClick,\n primaryButtonForeground,\n variant = \"primary\",\n}: {\n children: React.ReactNode;\n onClick: () => void;\n primaryButtonForeground: string;\n variant?: \"primary\" | \"secondary\";\n}) {\n const isPrimary = variant === \"primary\";\n return (\n \n {children}\n \n );\n}\n\nfunction WarningStatusIcon({ tone = \"red\" }: { tone?: \"orange\" | \"red\" }) {\n const color = tone === \"orange\" ? \"#F59E0B\" : \"#E8453C\";\n const backgroundColor = tone === \"orange\" ? \"#FFF7ED\" : \"#FEF2F2\";\n return (\n \n \n \n \n \n \n );\n}\n\nfunction OnrampActionStatusPanel({\n description,\n onPrimary,\n onSecondary,\n primaryButtonForeground,\n primaryLabel,\n secondaryLabel,\n title,\n}: {\n description: string;\n onPrimary: () => void;\n onSecondary: () => void;\n primaryButtonForeground: string;\n primaryLabel: string;\n secondaryLabel: string;\n title: string;\n}) {\n return (\n \n \n
\n
{title}
\n
{description}
\n
\n \n \n {primaryLabel}\n \n \n {secondaryLabel}\n \n \n \n );\n}\n\nfunction TimelineMarker({\n isComplete,\n isLast,\n isPending,\n}: {\n isComplete?: boolean;\n isLast?: boolean;\n isPending?: boolean;\n}) {\n return (\n \n \n {isComplete ? (\n \n ) : (\n \n )}\n \n {!isLast && (\n \n )}\n \n );\n}\n\nconst primaryButtonContrastColor = \"#FFFFFE\";\n\nfunction TimelineStep({\n isComplete,\n isLast,\n isPending,\n subtitle,\n title,\n}: {\n isComplete?: boolean;\n isLast?: boolean;\n isPending?: boolean;\n subtitle: string;\n title: string;\n}) {\n return (\n \n \n \n \n {title}\n \n \n {subtitle}\n \n \n \n );\n}\n\ntype OnrampTimelineItem = {\n complete?: boolean;\n pending?: boolean;\n subtitle: string;\n title: string;\n};\n\nfunction OnrampExpandableTimelineCard({\n summaryAmount,\n summaryLabel,\n steps,\n}: {\n summaryAmount: string;\n summaryLabel: string;\n steps: OnrampTimelineItem[];\n}) {\n const [expanded, setExpanded] = React.useState(true);\n return (\n \n setExpanded((current) => !current)}\n style={{\n alignItems: \"center\",\n background: \"transparent\",\n border: \"none\",\n color: theme.colors.textStrong,\n cursor: \"pointer\",\n display: \"flex\",\n fontFamily: theme.fonts.sans,\n fontSize: \"14px\",\n gap: \"10px\",\n justifyContent: \"space-between\",\n lineHeight: \"20px\",\n padding: \"12px 14px\",\n textAlign: \"left\",\n width: \"100%\",\n }}\n type=\"button\"\n >\n {summaryLabel}\n \n {summaryAmount}\n \n \n \n \n \n \n {steps.map((step, index) => (\n \n ))}\n \n \n \n \n );\n}\n\nfunction OnrampProcessingTimelinePanel({\n destinationAmount,\n destinationChainName,\n destinationSymbol,\n isSettling,\n provider,\n sourceAmount,\n sourceCurrencyCode,\n targetLabel,\n}: {\n destinationAmount: string;\n destinationChainName: string;\n destinationSymbol?: string;\n isSettling: boolean;\n provider?: string;\n sourceAmount: string;\n sourceCurrencyCode: string;\n targetLabel: string;\n}) {\n const destinationDisplay = formatTokenAmountDisplay(\n destinationAmount,\n destinationSymbol,\n );\n const sourceDisplay = formatCurrencyAmount(sourceAmount, sourceCurrencyCode);\n return (\n <>\n \n Usually takes 2 - 5 min\n \n \n \n \n \n \n \n );\n}\n\nfunction OnrampCompletingDepositPanel({\n depositExecution,\n destinationAmount,\n destinationChainName,\n destinationSymbol,\n gasShortfallInfo,\n gasTokenSymbol,\n provider,\n sourceAmount,\n sourceCurrencyCode,\n targetLabel,\n}: {\n depositExecution?: OnrampDepositExecutionState;\n destinationAmount: string;\n destinationChainName: string;\n destinationSymbol?: string;\n gasShortfallInfo?: OnrampGasShortfallInfo | null;\n gasTokenSymbol?: string;\n provider?: string;\n sourceAmount: string;\n sourceCurrencyCode: string;\n targetLabel: string;\n}) {\n const destinationDisplay = formatTokenAmountDisplay(\n destinationAmount,\n destinationSymbol,\n );\n const sourceDisplay = formatCurrencyAmount(sourceAmount, sourceCurrencyCode);\n const isSwappingGas = depositExecution?.step === \"swapping_gas\";\n const hasGasSwap = Boolean(\n gasShortfallInfo?.isShortfall &&\n gasShortfallInfo.shortfallAmountRaw > BigInt(0),\n );\n const gasSwapDone = hasGasSwap && depositExecution?.step === \"depositing\";\n\n const steps = [\n {\n complete: true,\n subtitle: `${sourceDisplay} by ${getProviderLabel(provider)}`,\n title: \"Payment received\",\n },\n {\n complete: true,\n subtitle: `On ${destinationChainName}`,\n title: `Sent ${destinationDisplay} to your wallet`,\n },\n ...(hasGasSwap\n ? [\n {\n complete: gasSwapDone,\n subtitle: `Swapping ${gasShortfallInfo?.shortfallAmountEth ?? \"\"} ${\n gasTokenSymbol ?? \"gas\"\n } on ${destinationChainName}`,\n title: `Swap for gas (${gasTokenSymbol ?? \"gas\"})`,\n },\n ]\n : []),\n {\n complete: false,\n subtitle: `On ${destinationChainName}`,\n title: `Depositing on ${targetLabel}`,\n },\n ];\n\n return (\n <>\n \n {isSwappingGas ? \"Swapping for gas...\" : \"Usually takes 20 seconds\"}\n \n \n \n \n \n \n \n );\n}\n\nfunction OnrampSuccessPanel({\n destinationAmount,\n destinationSymbol,\n explorerUrl,\n onDone,\n paymentMethod,\n primaryButtonForeground,\n provider,\n sourceAmount,\n sourceCurrencyCode,\n subtitle,\n}: {\n destinationAmount: string;\n destinationSymbol?: string;\n explorerUrl?: string;\n onDone: () => void;\n paymentMethod?: string;\n primaryButtonForeground: string;\n provider?: string;\n sourceAmount: string;\n sourceCurrencyCode: string;\n subtitle: string;\n}) {\n return (\n <>\n \n {subtitle}\n \n \n \n
Transaction Summary
\n \n {paymentMethod && (\n \n )}\n \n \n \n \n \n {explorerUrl && (\n \n \n View Explorer\n \n \n )}\n \n Done\n \n \n );\n}\n\nfunction SummaryRow({ label, value }: { label: string; value: string }) {\n return (\n \n \n {label}\n \n \n {value}\n \n \n );\n}\n\nfunction OnrampHandoffPanel({\n destinationChainName,\n provider,\n summaryAmount,\n targetLabel,\n}: {\n destinationChainName: string;\n provider?: string;\n summaryAmount: string;\n targetLabel: string;\n}) {\n return (\n <>\n \n The payment processor requires some information\n \n \n \n \n \n \n );\n}\n\nfunction OnrampSessionStatusPanel({\n hasConnectedWallet,\n walletChecking,\n onConnectWallet,\n depositExecution,\n gasShortfallInfo,\n onCancel,\n onDone,\n onRetryDeposit,\n onRetryPayment,\n opportunity,\n primaryButtonForeground,\n quote,\n session,\n sessionCallbackReceived,\n sourceAmount,\n sourceCurrencyCode,\n toToken,\n}: {\n hasConnectedWallet: boolean;\n walletChecking: boolean;\n onConnectWallet: () => void;\n depositExecution: OnrampDepositExecutionState;\n gasShortfallInfo?: OnrampGasShortfallInfo | null;\n onCancel: () => void;\n onDone: () => void;\n onRetryDeposit: () => void;\n onRetryPayment: () => void;\n opportunity?: NexusWidgetDepositOpportunityConfig;\n primaryButtonForeground: string;\n quote?: OnrampQuote;\n session: OnrampSessionResponse;\n sessionCallbackReceived: boolean;\n sourceAmount: string;\n sourceCurrencyCode: string;\n toToken?: SwapTokenOption;\n}) {\n const normalizedState =\n getNormalizedOnrampState(session.state) || \"AWAITING_USER\";\n const provider = session.provider ?? quote?.provider;\n const transaction = session.transaction;\n const destinationSymbol = toToken?.symbol ?? quote?.destinationCurrencyCode;\n const destinationAmount =\n depositExecution.amount ??\n transaction?.destinationAmount ??\n quote?.destinationAmount ??\n \"\";\n const sourceDisplayAmount =\n transaction?.sourceAmount ?? quote?.sourceAmount ?? sourceAmount;\n const sourceDisplayCurrency =\n transaction?.sourceCurrencyCode ??\n quote?.sourceCurrencyCode ??\n sourceCurrencyCode;\n const destinationChainName = getDepositChainName(opportunity, toToken);\n const targetLabel = getDepositTargetLabel(opportunity);\n const destinationChainId = toToken?.chainId ?? opportunity?.chainId ?? 0;\n const gasTokenSymbol =\n CHAIN_METADATA[destinationChainId]?.nativeCurrency?.symbol ?? \"ETH\";\n const explorerUrl =\n depositExecution.explorerUrl ?? getOnrampExplorerUrl(session, toToken);\n const containerStyle: React.CSSProperties = {\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"12px\",\n width: \"100%\",\n };\n\n if (\n [\"FAILED\", \"DECLINED\", \"AUTHORIZATION_EXPIRED\"].includes(normalizedState)\n ) {\n return (\n
\n \n
\n );\n }\n\n if ([\"CANCELLED\", \"EXPIRED\", \"REFUNDED\"].includes(normalizedState)) {\n const title =\n normalizedState === \"CANCELLED\"\n ? \"Payment cancelled\"\n : normalizedState === \"REFUNDED\"\n ? \"Payment refunded\"\n : \"Payment expired\";\n const description =\n normalizedState === \"CANCELLED\"\n ? \"No payment was completed.\"\n : normalizedState === \"REFUNDED\"\n ? `${getProviderLabel(provider)} refunded the payment.`\n : \"Start a new local currency payment to continue.\";\n return (\n
\n \n
\n );\n }\n\n if (\n normalizedState === \"SETTLED\" &&\n depositExecution.status !== \"success\" &&\n depositExecution.status !== \"running\" &&\n !hasConnectedWallet\n ) {\n return (\n \n );\n }\n\n if (\n depositExecution.status === \"failed\" ||\n isOnrampDepositFailedState(normalizedState)\n ) {\n return (\n
\n \n
\n );\n }\n\n if (depositExecution.status === \"success\") {\n return (\n
\n \n
\n );\n }\n\n if (\n normalizedState === \"SETTLED\" ||\n depositExecution.status === \"running\" ||\n isOnrampDepositProcessingState(normalizedState)\n ) {\n return (\n
\n \n
\n );\n }\n\n if (sessionCallbackReceived) {\n return (\n
\n \n
\n );\n }\n\n if (isOnrampProcessingState(normalizedState)) {\n return (\n
\n \n
\n );\n }\n\n return (\n
\n \n
\n );\n}\n\nexport function DepositOnrampFlow({\n baseUrl = getOnrampBaseUrl(),\n getWalletProvider,\n walletConnected,\n destinationTokens,\n onConnectWallet,\n onError,\n onSelectDestinationToken,\n onSessionStateChange,\n onSessionUpdate,\n nexusSDK,\n ownerAddress: persistedOwnerAddress,\n opportunity,\n primaryButtonForeground,\n toToken,\n walletClient,\n}: DepositOnrampFlowProps) {\n const {\n address: ownerAddress,\n revision: walletRevision,\n checking: walletChecking,\n check: checkWalletConnection,\n } = useOnrampWallet({\n getProvider: getWalletProvider,\n walletClient,\n walletConnected,\n });\n const [walletActionPending, setWalletActionPending] = React.useState(false);\n const [countryCode, setCountryCode] = React.useState(\"\");\n const [sourceCurrencyCode, setSourceCurrencyCode] = React.useState(\"\");\n const [sourceAmount, setSourceAmount] = React.useState(\"\");\n const [options, setOptions] = React.useState(\n null,\n );\n const [routes, setRoutes] = React.useState([]);\n const [selectedPaymentMethod, setSelectedPaymentMethod] = React.useState(\"\");\n const [quotes, setQuotes] = React.useState([]);\n const [quotesRequestKey, setQuotesRequestKey] = React.useState(\"\");\n const [selectedProvider, setSelectedProvider] = React.useState(\"\");\n const [activeSheet, setActiveSheet] = React.useState(null);\n const [countrySearch, setCountrySearch] = React.useState(\"\");\n const [currencySearch, setCurrencySearch] = React.useState(\"\");\n const [methodSearch, setMethodSearch] = React.useState(\"\");\n const [partnerSearch, setPartnerSearch] = React.useState(\"\");\n const [optionsLoading, setOptionsLoading] = React.useState(false);\n const [routesLoading, setRoutesLoading] = React.useState(false);\n const [quotesLoading, setQuotesLoading] = React.useState(false);\n const [sessionLoading, setSessionLoading] = React.useState(false);\n const [error, setError] = React.useState(null);\n const [blockedRateRequest, setBlockedRateRequest] =\n React.useState(null);\n const [failedQuoteRequest, setFailedQuoteRequest] =\n React.useState(null);\n const [session, setSession] = React.useState(\n null,\n );\n const [sessionCallbackReceived, setSessionCallbackReceived] =\n React.useState(false);\n const [depositExecution, setDepositExecution] =\n React.useState({ status: \"idle\" });\n const [gasShortfallInfo, setGasShortfallInfo] =\n React.useState(null);\n const [gasShortfallLoading, setGasShortfallLoading] = React.useState(false);\n const [forexRates, setForexRates] = React.useState>(\n {},\n );\n const [quoteRefreshSeconds, setQuoteRefreshSeconds] = React.useState(\n QUOTE_REFRESH_SECONDS,\n );\n const [quoteRefreshProgress, setQuoteRefreshProgress] = React.useState(1);\n const userSelectedCountryRef = React.useRef(\n readOnrampCache(ONRAMP_USER_COUNTRY_CACHE_KEY) || \"\",\n );\n const onErrorRef = React.useRef(onError);\n onErrorRef.current = onError;\n const sessionRef = React.useRef(session);\n sessionRef.current = session;\n const sessionHistoryRef = React.useRef | null>(null);\n const sessionQuoteRef = React.useRef(null);\n const sessionUpdateRef = React.useRef(onSessionUpdate);\n sessionUpdateRef.current = onSessionUpdate;\n const ownerRef = React.useRef(ownerAddress);\n ownerRef.current = ownerAddress;\n const refreshSessionRef = React.useRef<(() => void) | null>(null);\n const depositAbortRef = React.useRef(null);\n const depositBusyRef = React.useRef(false);\n const remainingDepositRef = React.useRef<{\n sessionId: string;\n amountRaw: bigint;\n } | null>(null);\n const pendingApprovalRef = React.useRef<{\n sessionId: string;\n txHash: Hex;\n } | null>(null);\n const pendingDepositRef = React.useRef<{\n sessionId: string;\n txHash: Hex;\n amountRaw: bigint;\n } | null>(null);\n const quoteRunIdRef = React.useRef(0);\n const routeRunIdRef = React.useRef(0);\n const lastRouteRequestKeyRef = React.useRef(\"\");\n const lastQuoteRequestKeyRef = React.useRef(\"\");\n const quotesLoadingRef = React.useRef(false);\n const quoteAbortRef = React.useRef(null);\n const createSessionAbortRef = React.useRef(null);\n const depositExecutionSessionRef = React.useRef(\"\");\n const normalizedSessionState = getNormalizedOnrampState(session?.state);\n const hasConnectedWallet = Boolean(ownerAddress);\n const quoteWalletAddress = hasConnectedWallet\n ? (ownerAddress as Address)\n : ONRAMP_DISCONNECTED_QUOTE_WALLET_ADDRESS;\n\n const fiatCurrencyOptions = React.useMemo(\n () => getFiatCurrencyOptions(options),\n [options],\n );\n const selectedFiatCurrency = fiatCurrencyOptions.find(\n (currency) => currency.currencyCode === sourceCurrencyCode,\n );\n const filteredFiatCurrencies = React.useMemo(() => {\n const query = currencySearch.trim().toLowerCase();\n if (!query) return fiatCurrencyOptions;\n return fiatCurrencyOptions.filter((currency) => {\n const code = currency.currencyCode.toLowerCase();\n const name = (\n currency.name ?? getFiatCurrencyName(currency.currencyCode, currency)\n ).toLowerCase();\n const symbol = (currency.symbol ?? \"\").toLowerCase();\n return (\n code.includes(query) || name.includes(query) || symbol.includes(query)\n );\n });\n }, [fiatCurrencyOptions, currencySearch]);\n\n const filteredCountries = React.useMemo(() => {\n const list = options?.countries ?? [];\n const seen = new Set();\n const unique: OnrampCountry[] = [];\n for (const item of list) {\n const code = item.countryCode?.toUpperCase();\n if (!code || seen.has(code)) continue;\n seen.add(code);\n unique.push(item);\n }\n const query = countrySearch.trim().toLowerCase();\n if (!query) return unique;\n return unique.filter((country) => {\n const name = (country.name ?? \"\").toLowerCase();\n const code = (country.countryCode ?? \"\").toLowerCase();\n return name.includes(query) || code.includes(query);\n });\n }, [options?.countries, countrySearch]);\n\n const selectedCountry = React.useMemo(\n () => getCountryByCode(options?.countries, countryCode),\n [options?.countries, countryCode],\n );\n const selectedCountryFlagUrl =\n selectedCountry?.flagUrl ??\n getCountryFlagUrl(options?.countries, countryCode);\n\n const selectedOnrampCryptoCurrency = React.useMemo(\n () => getOnrampCryptoCurrency(options, toToken),\n [options, toToken],\n );\n const hasBackendCryptoCurrencyList = Array.isArray(\n options?.selection?.cryptoCurrencies,\n );\n const isDestinationTokenUnsupported = Boolean(\n hasBackendCryptoCurrencyList &&\n toToken?.chainId &&\n toToken.contractAddress &&\n !selectedOnrampCryptoCurrency,\n );\n const destinationTokenUnsupportedMessage = isDestinationTokenUnsupported\n ? \"Token is not supported for purchase with local currency\"\n : null;\n const availableDestinationTokens = React.useMemo(() => {\n const tokens = destinationTokens?.length\n ? destinationTokens\n : toToken\n ? [toToken]\n : [];\n const byKey = new Map();\n for (const token of tokens) {\n const key = getOnrampTokenKey(token);\n if (!key) continue;\n const onrampCurrency = getOnrampCryptoCurrency(options, token);\n byKey.set(key, {\n ...token,\n logo: onrampCurrency?.symbolUrl ?? token.logo,\n name: token.name ?? onrampCurrency?.name,\n });\n }\n return Array.from(byKey.values());\n }, [destinationTokens, options, toToken]);\n const destinationRequestDetails = React.useMemo(\n () => getDestinationRequestDetails(options, toToken),\n [options, toToken],\n );\n const rateRequestKey = React.useMemo(\n () =>\n getOnrampRateRequestKey({\n countryCode,\n destinationChainId: destinationRequestDetails.destinationChainId,\n destinationCurrencyCode:\n destinationRequestDetails.destinationCurrencyCode,\n destinationToken: destinationRequestDetails.destinationToken,\n sourceCurrencyCode,\n }),\n [\n countryCode,\n destinationRequestDetails.destinationChainId,\n destinationRequestDetails.destinationCurrencyCode,\n destinationRequestDetails.destinationToken,\n sourceCurrencyCode,\n ],\n );\n const quoteRequestKey = React.useMemo(\n () =>\n [\n rateRequestKey,\n quoteWalletAddress.toLowerCase(),\n walletRevision,\n selectedPaymentMethod,\n sourceAmount.trim(),\n ].join(\"|\"),\n [\n quoteWalletAddress,\n walletRevision,\n rateRequestKey,\n selectedPaymentMethod,\n sourceAmount,\n ],\n );\n const selectedRoute = React.useMemo(\n () =>\n routes.find((route) => route.provider === selectedProvider) ?? routes[0],\n [routes, selectedProvider],\n );\n const availablePaymentMethods = React.useMemo(() => {\n const map = new Map();\n const sourceRoutes = selectedRoute ? [selectedRoute] : routes;\n for (const route of sourceRoutes) {\n for (const method of route.paymentMethods ?? []) {\n if (!method.method || map.has(method.method)) continue;\n map.set(method.method, method);\n }\n }\n const list = Array.from(map.values());\n cacheOnrampPaymentMethods(list);\n return list;\n }, [routes, selectedRoute]);\n const selectedPaymentMethodDetails = availablePaymentMethods.find(\n (method) => method.method === selectedPaymentMethod,\n );\n const currentQuotes = React.useMemo(\n () => (quotesRequestKey === quoteRequestKey ? quotes : []),\n [quoteRequestKey, quotes, quotesRequestKey],\n );\n const selectedQuote =\n currentQuotes.find(\n (quote) =>\n quote.provider === selectedProvider &&\n (!selectedPaymentMethod ||\n quote.paymentMethodType === selectedPaymentMethod),\n ) ??\n currentQuotes.find((quote) => quote.provider === selectedProvider) ??\n currentQuotes.find(\n (quote) => quote.paymentMethodType === selectedPaymentMethod,\n ) ??\n currentQuotes[0];\n const filteredPaymentMethods = React.useMemo(\n () =>\n availablePaymentMethods.filter((method) =>\n matchesSearch(methodSearch, [\n method.method,\n method.name,\n getMethodLabel(method.method),\n getMethodSubtitle(method),\n ]),\n ),\n [availablePaymentMethods, methodSearch],\n );\n const providerOptions = React.useMemo(() => {\n if (currentQuotes.length > 0) {\n return currentQuotes.map((quote) => {\n const route = routes.find(\n (candidate) => candidate.provider === quote.provider,\n );\n const paymentMethod = route?.paymentMethods?.find(\n (method) => method.method === quote.paymentMethodType,\n );\n return {\n destinationAmount: quote.destinationAmount,\n paymentMethod,\n paymentMethodType: quote.paymentMethodType,\n provider: quote.provider,\n quote,\n route,\n };\n });\n }\n return routes\n .filter((route) => route.provider)\n .map((route) => ({\n paymentMethod: route.paymentMethods?.[0],\n paymentMethodType: route.paymentMethods?.[0]?.method,\n provider: route.provider,\n route,\n }));\n }, [currentQuotes, routes]);\n const filteredProviderOptions = React.useMemo(\n () =>\n providerOptions.filter((option) =>\n matchesSearch(partnerSearch, [\n option.provider,\n getProviderLabel(option.provider),\n option.paymentMethodType,\n option.paymentMethod?.name,\n getMethodLabel(option.paymentMethodType),\n getMethodSubtitle(option.paymentMethod),\n ]),\n ),\n [partnerSearch, providerOptions],\n );\n const hasMultipleCurrencies = fiatCurrencyOptions.length > 1;\n const hasMultipleDestinationTokens = availableDestinationTokens.length > 1;\n const hasMultipleMethods = availablePaymentMethods.length > 1;\n const hasMultipleProviders = providerOptions.length > 1;\n const parsedSourceAmount = React.useMemo(\n () => parseDecimal(sourceAmount),\n [sourceAmount],\n );\n const hasPositiveSourceAmount = Boolean(parsedSourceAmount?.gt(0));\n const amountLimitMessage = (() => {\n const limits = selectedPaymentMethodDetails?.limits;\n if (!limits || !parsedSourceAmount?.gt(0)) return null;\n const min = parseDecimal(limits.min);\n const max = parseDecimal(limits.max);\n if (min && parsedSourceAmount.lt(min)) {\n return `Minimum ${formatCurrencyAmount(min, sourceCurrencyCode)}`;\n }\n if (max && parsedSourceAmount.gt(max)) {\n return `Maximum ${formatCurrencyAmount(max, sourceCurrencyCode)}`;\n }\n return null;\n })();\n\n const targetChainId = toToken?.chainId ?? opportunity?.chainId;\n const isErc20 = isErc20Token(toToken, targetChainId);\n\n React.useEffect(() => {\n if (!targetChainId || !isErc20) {\n setGasShortfallInfo(null);\n setGasShortfallLoading(false);\n return;\n }\n\n let cancelled = false;\n setGasShortfallLoading(true);\n\n const runGasShortfallCheck = async () => {\n try {\n // 1. Gas units from opportunity executeDeposit:\n let configGas = BigInt(1000000);\n let hasApproval = false;\n if (opportunity?.executeDeposit) {\n try {\n const dummyAmountRaw = BigInt(1000000);\n const dummyUser =\n ownerAddress && isAddress(ownerAddress)\n ? (ownerAddress as Address)\n : ONRAMP_DISCONNECTED_QUOTE_WALLET_ADDRESS;\n const executeParams = opportunity.executeDeposit(\n opportunity.tokenSymbol,\n opportunity.tokenAddress,\n dummyAmountRaw,\n targetChainId,\n dummyUser,\n );\n if (executeParams?.gas && executeParams.gas > BigInt(0)) {\n configGas = executeParams.gas;\n }\n if (executeParams?.tokenApproval) {\n hasApproval = true;\n }\n } catch (e) {\n logOnramp(\n \"Could not simulate executeDeposit for gas estimation, using default 1M gas\",\n e,\n );\n }\n }\n const estimatedGasUnits =\n configGas + (hasApproval ? BigInt(50000) : BigInt(0));\n\n // 2. Fetch destination gas price:\n const gasPriceWei = await fetchDestinationGasPriceWei(\n targetChainId,\n walletClient,\n nexusSDK,\n );\n\n if (cancelled) return;\n\n // 3. Wei calculation with 20% safety margin:\n const rawGasCostWei = estimatedGasUnits * gasPriceWei;\n const requiredGasWei = (rawGasCostWei * BigInt(120)) / BigInt(100);\n\n // 4. Native decimals & ETH conversion:\n const nativeDecimals =\n CHAIN_METADATA[targetChainId]?.nativeCurrency?.decimals ?? 18;\n const requiredGasEth = new Decimal(requiredGasWei.toString())\n .div(Decimal.pow(10, nativeDecimals))\n .toFixed();\n\n // 5. User balance & shortfall:\n let userGasBalanceWei = BigInt(0);\n if (ownerAddress && isAddress(ownerAddress)) {\n userGasBalanceWei = await fetchUserNativeGasBalanceWei(\n ownerAddress as Address,\n targetChainId,\n walletClient,\n nexusSDK,\n );\n }\n const userGasBalanceEth = new Decimal(userGasBalanceWei.toString())\n .div(Decimal.pow(10, nativeDecimals))\n .toFixed();\n\n const gasDiffWei = userGasBalanceWei - requiredGasWei;\n const isShortfall = isErc20 && gasDiffWei < BigInt(0);\n const shortfallAmountRaw = isShortfall\n ? requiredGasWei - userGasBalanceWei\n : BigInt(0);\n const shortfallAmountEth = isShortfall\n ? new Decimal(shortfallAmountRaw.toString())\n .div(Decimal.pow(10, nativeDecimals))\n .toFixed()\n : \"0\";\n\n if (!cancelled) {\n setGasShortfallInfo({\n estimatedGasUnits,\n gasPriceWei,\n hasApproval,\n isErc20: true,\n isShortfall,\n requiredGasEth,\n requiredGasWei,\n shortfallAmountEth,\n shortfallAmountRaw,\n userGasBalanceEth,\n userGasBalanceWei,\n });\n }\n } catch (err) {\n logOnramp(\"Failed to check gas shortfall:\", err);\n if (!cancelled) {\n setGasShortfallInfo(null);\n }\n } finally {\n if (!cancelled) {\n setGasShortfallLoading(false);\n }\n }\n };\n\n void runGasShortfallCheck();\n\n return () => {\n cancelled = true;\n };\n }, [\n targetChainId,\n isErc20,\n opportunity,\n ownerAddress,\n walletClient,\n nexusSDK,\n ]);\n\n const executeOnrampDeposit = React.useCallback(\n async (force = false) => {\n const sessionId = session?.sessionId;\n logOnramp(\"deposit.handoff\", {\n sessionId,\n state: session?.state,\n force,\n hasOpportunity: Boolean(opportunity),\n hasWallet: Boolean(walletClient),\n hasSDK: Boolean(nexusSDK),\n ownerAddress,\n persistedOwnerAddress,\n });\n if (\n !sessionId ||\n depositBusyRef.current ||\n depositExecution.status === \"success\"\n )\n return;\n if (!force && depositExecutionSessionRef.current === sessionId) return;\n depositExecutionSessionRef.current = sessionId;\n depositBusyRef.current = true;\n const controller = new AbortController();\n depositAbortRef.current = controller;\n const checkActive = () => {\n controller.signal.throwIfAborted();\n if (\n sessionRef.current?.sessionId !== sessionId ||\n ownerRef.current !== ownerAddress\n ) {\n throw new Error(\n \"The wallet or onramp session changed. Reconnect the funded wallet to continue.\",\n );\n }\n };\n setDepositExecution({ status: \"running\", step: \"depositing\" });\n try {\n checkActive();\n let settledSession = session;\n if (force && !pendingDepositRef.current) {\n const payload = await fetchOnrampJson(\n baseUrl,\n `/api/v1/onramp/sessions/${encodeURIComponent(sessionId)}`,\n { signal: controller.signal },\n );\n checkActive();\n settledSession = mergeOnrampSession(\n session,\n normalizeOnrampSession(payload, sessionId),\n );\n setSession(settledSession);\n }\n if (!opportunity || !toToken || !ownerAddress || !walletClient) {\n throw new Error(\n \"Reconnect your wallet to complete the deposit. Your purchased crypto remains in your wallet.\",\n );\n }\n const account = ownerAddress as Address;\n const liveAccount = await checkWalletConnection();\n if (liveAccount?.toLowerCase() !== account.toLowerCase()) {\n throw new Error(\n \"Reconnect the funded wallet to complete your deposit.\",\n );\n }\n checkActive();\n const toChainId = opportunity.chainId;\n const decimals = opportunity.tokenDecimals;\n if (\n !isMatchingOnrampToken(toToken, toChainId, opportunity.tokenAddress)\n ) {\n throw new Error(\n \"The onramp token does not match the configured deposit destination.\",\n );\n }\n if (\n settledSession.transaction?.walletAddress &&\n settledSession.transaction.walletAddress.toLowerCase() !==\n account.toLowerCase()\n ) {\n throw new Error(\n \"Connect the wallet that received this onramp payment to deposit.\",\n );\n }\n if (\n settledSession.transaction?.chainId &&\n settledSession.transaction.chainId !== toChainId\n ) {\n throw new Error(\n \"The payment was delivered on a different chain than the deposit destination.\",\n );\n }\n const confirm = (hash: Hex) =>\n waitForWalletTransactionSuccess(\n walletClient,\n hash,\n toChainId,\n nexusSDK,\n controller.signal,\n );\n const markSuccess = (txHash: Hex, amountRaw: bigint) => {\n checkActive();\n const amount = formatUnits(amountRaw, decimals);\n const explorerUrl = getNexusChainTransactionExplorerUrl(\n nexusSDK,\n toChainId,\n txHash,\n );\n logOnramp(\"deposit.confirmed\", {\n sessionId,\n txHash,\n toChainId,\n amount,\n explorerUrl,\n });\n setDepositExecution({\n amount,\n explorerUrl,\n status: \"success\",\n txHash,\n });\n // Keep the authoritative Meld state separate from local execution state.\n pendingDepositRef.current = null;\n };\n const pending = pendingDepositRef.current;\n if (pending?.sessionId === sessionId) {\n logOnramp(\"deposit.resume_confirmation\", pending);\n await confirm(pending.txHash);\n markSuccess(pending.txHash, pending.amountRaw);\n return;\n }\n if (pendingApprovalRef.current?.sessionId === sessionId) {\n logOnramp(\n \"wallet.approval.resume_confirmation\",\n pendingApprovalRef.current,\n );\n await confirm(pendingApprovalRef.current.txHash);\n pendingApprovalRef.current = null;\n }\n // Quotes are estimates. Only the settled transaction establishes the amount to deposit.\n let amountRaw =\n remainingDepositRef.current?.sessionId === sessionId\n ? remainingDepositRef.current.amountRaw\n : getRawTokenAmount(\n settledSession.transaction?.destinationAmount,\n decimals,\n );\n if (!amountRaw || amountRaw <= BigInt(0))\n throw new Error(\n \"The settled payment is missing its received amount. Check payment status again before depositing.\",\n );\n logOnramp(\"deposit.amount\", {\n sessionId,\n amountRaw,\n decimals,\n state: settledSession.state,\n });\n if (settledSession.state !== \"SETTLED\")\n throw new Error(\"The payment has not settled yet.\");\n logOnramp(\"wallet.switch_chain\", { sessionId, toChainId });\n const chainHex = await walletClient.request({ method: \"eth_chainId\" });\n if (Number(chainHex) !== toChainId)\n await walletClient.switchChain({ id: toChainId });\n const assertWallet = async () => {\n checkActive();\n const liveAccount = await checkWalletConnection();\n const [chainId, accounts] = await Promise.all([\n walletClient.request({ method: \"eth_chainId\" }),\n walletClient.request({ method: \"eth_accounts\" }),\n ]);\n checkActive();\n if (\n liveAccount?.toLowerCase() !== account.toLowerCase() ||\n Number(chainId) !== toChainId ||\n accounts[0]?.toLowerCase() !== account.toLowerCase()\n ) {\n throw new Error(\n \"Select the funded wallet and deposit chain to continue.\",\n );\n }\n };\n await assertWallet();\n const readTokenBalance = async () => {\n const isNative = isNativeAddress(opportunity.tokenAddress);\n const method = isNative ? \"eth_getBalance\" : \"eth_call\";\n const params = isNative\n ? [account, \"latest\"]\n : [\n {\n to: opportunity.tokenAddress,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"balanceOf\",\n args: [account],\n }),\n },\n \"latest\",\n ];\n const rpc = getChainRpcUrl(toChainId, nexusSDK);\n const balance = rpc\n ? await makeJsonRpcCall(\n rpc,\n method,\n params,\n controller.signal,\n )\n : ((await walletClient.request({\n method,\n params,\n } as any)) as string);\n checkActive();\n logOnramp(\"deposit.balance\", {\n sessionId,\n toChainId,\n balanceRaw: BigInt(balance),\n requiredRaw: amountRaw,\n });\n return BigInt(balance);\n };\n // Allow RPC visibility to catch up with 60 one-second retries after Meld reports delivery.\n let balanceBefore = await readTokenBalance();\n for (\n let attempt = 0;\n balanceBefore < amountRaw && attempt < 60;\n attempt++\n ) {\n logOnramp(\"deposit.awaiting_balance\", { sessionId, attempt });\n await onrampDelay(1000, controller.signal);\n balanceBefore = await readTokenBalance();\n }\n if (balanceBefore < amountRaw)\n throw new Error(\n \"The settled amount is not yet available on the deposit chain. Retry Deposit after the balance arrives.\",\n );\n const makeExecuteParams = () =>\n opportunity.executeDeposit(\n opportunity.tokenSymbol,\n opportunity.tokenAddress,\n amountRaw!,\n toChainId,\n account,\n );\n let executeParams = makeExecuteParams();\n if (!isPositiveGasLimit(executeParams.gas))\n throw new Error(\n \"Deposit config executeDeposit must return a positive gas limit.\",\n );\n // Refresh gas at settlement: checkout may have taken several minutes.\n const [gasPrice, nativeBalance] = await Promise.all([\n fetchDestinationGasPriceWei(toChainId, walletClient, nexusSDK),\n fetchUserNativeGasBalanceWei(\n account,\n toChainId,\n walletClient,\n nexusSDK,\n ),\n ]);\n checkActive();\n const gasUnits =\n executeParams.gas +\n (executeParams.tokenApproval ? BigInt(50_000) : BigInt(0));\n const gasRequired = (gasUnits * gasPrice * BigInt(120)) / BigInt(100);\n const shortfall =\n gasRequired > nativeBalance ? gasRequired - nativeBalance : BigInt(0);\n logOnramp(\"deposit.gas_check\", {\n sessionId,\n gasUnits,\n gasPrice,\n nativeBalance,\n gasRequired,\n shortfall,\n });\n if (\n isNativeAddress(opportunity.tokenAddress) &&\n nativeBalance < amountRaw + gasRequired\n ) {\n throw new Error(\n \"Additional native gas is needed to deposit the purchased amount. Add gas to this wallet and retry Deposit.\",\n );\n }\n if (isErc20Token(toToken, toChainId) && shortfall > BigInt(0)) {\n if (!nexusSDK?.swapWithExactOut)\n throw new Error(\n \"Nexus is not ready to acquire gas for the deposit. Reconnect and retry.\",\n );\n await assertWallet();\n setDepositExecution({ status: \"running\", step: \"swapping_gas\" });\n const input = {\n sources: [\n { chainId: toChainId, tokenAddress: opportunity.tokenAddress },\n ],\n toAmountRaw: shortfall,\n toChainId,\n toTokenAddress: zeroAddress,\n };\n logOnramp(\"sdk.swapWithExactOut.start\", { sessionId, input });\n const result = await nexusSDK.swapWithExactOut(input, {\n hooks: {\n onIntent: (data: any) => {\n logOnramp(\"sdk.intent\", { sessionId, intent: data.intent });\n try {\n checkActive();\n } catch {\n data.deny();\n return;\n }\n try {\n const spend = (data.intent?.sources ?? []).reduce(\n (total: bigint, source: any) => {\n if (\n !isMatchingOnrampToken(\n toToken,\n source.chain.id,\n source.token.contractAddress,\n )\n )\n throw new Error(\n \"Gas quote uses an unexpected source token.\",\n );\n return (\n total + parseUnits(source.amount, source.token.decimals)\n );\n },\n BigInt(0),\n );\n if (spend >= amountRaw!) {\n logOnramp(\"sdk.intent.denied\", {\n sessionId,\n reason: \"Gas quote consumes the purchased amount\",\n spend,\n amountRaw,\n });\n data.deny();\n return;\n }\n logOnramp(\"sdk.intent.allow\", { sessionId, spend });\n data.allow();\n } catch (error) {\n logOnramp(\"sdk.intent.denied\", { sessionId, error });\n data.deny();\n }\n },\n },\n onEvent: (event: any) =>\n logOnramp(\"sdk.event\", {\n sessionId,\n operation: \"swapWithExactOut\",\n event,\n }),\n });\n checkActive();\n logOnramp(\"sdk.swapWithExactOut.complete\", { sessionId, result });\n amountRaw = getOnrampRemainingAmount(\n amountRaw,\n balanceBefore,\n await readTokenBalance(),\n );\n remainingDepositRef.current = { sessionId, amountRaw };\n executeParams = makeExecuteParams();\n setDepositExecution({ status: \"running\", step: \"depositing\" });\n }\n logOnramp(\"deposit.execute_config\", {\n sessionId,\n amountRaw,\n executeParams,\n });\n if (!isPositiveGasLimit(executeParams.gas))\n throw new Error(\n \"Deposit config executeDeposit must return a positive gas limit.\",\n );\n if (executeParams.tokenApproval) {\n await assertWallet();\n const approval = executeParams.tokenApproval;\n const allowanceData = encodeFunctionData({\n abi: erc20Abi,\n functionName: \"allowance\",\n args: [account, approval.spender],\n });\n const allowance = BigInt(\n (await walletClient.request({\n method: \"eth_call\",\n params: [\n { to: approval.toTokenAddress, data: allowanceData },\n \"latest\",\n ],\n } as any)) as string,\n );\n logOnramp(\"wallet.approval.check\", {\n sessionId,\n allowance,\n required: approval.amount,\n });\n if (allowance < approval.amount) {\n await assertWallet();\n logOnramp(\"wallet.approval.prompt\", { sessionId, approval });\n const approvalHash = await walletClient.writeContract({\n abi: erc20Abi,\n account,\n address: approval.toTokenAddress,\n args: [approval.spender, approval.amount],\n chain: null,\n functionName: \"approve\",\n });\n pendingApprovalRef.current = { sessionId, txHash: approvalHash };\n logOnramp(\"wallet.approval.submitted\", { sessionId, approvalHash });\n await confirm(approvalHash);\n pendingApprovalRef.current = null;\n }\n }\n await assertWallet();\n logOnramp(\"wallet.deposit.prompt\", {\n sessionId,\n toChainId,\n amountRaw,\n to: executeParams.to,\n });\n const txHash = await walletClient.sendTransaction({\n account,\n chain: null,\n data: executeParams.data,\n gas: executeParams.gas,\n to: executeParams.to,\n value: executeParams.value,\n });\n // Preserve the hash before waiting: retry must check this transaction, never send a second deposit.\n pendingDepositRef.current = { sessionId, txHash, amountRaw };\n logOnramp(\"wallet.deposit.submitted\", { sessionId, txHash, amountRaw });\n await confirm(txHash);\n markSuccess(txHash, amountRaw);\n } catch (depositError) {\n logOnramp(\"deposit.error\", {\n sessionId,\n pending: pendingDepositRef.current,\n error: depositError,\n });\n if (controller.signal.aborted) return;\n if (\n depositError instanceof Error &&\n depositError.message === \"Transaction reverted on chain.\"\n ) {\n pendingDepositRef.current = null;\n pendingApprovalRef.current = null;\n }\n const message = getErrorMessage(depositError);\n setDepositExecution({\n error: message,\n status: \"failed\",\n txHash: pendingDepositRef.current?.txHash,\n });\n onErrorRef.current?.(message);\n } finally {\n depositBusyRef.current = false;\n if (depositAbortRef.current === controller)\n depositAbortRef.current = null;\n logOnramp(\"deposit.run_finished\", { sessionId });\n }\n },\n [\n baseUrl,\n checkWalletConnection,\n depositExecution.status,\n opportunity,\n ownerAddress,\n persistedOwnerAddress,\n nexusSDK,\n session,\n toToken,\n walletClient,\n ],\n );\n\n const applyOptions = React.useCallback(\n (data: OnrampOptionsResponse, fallbackCountryCode: string) => {\n cacheOnrampProviders(data.providers);\n cacheOnrampFiatMetadata(\n data.selection?.fiatCurrencyMetadata ?? data.fiatCurrencyMetadata,\n );\n setOptions(data);\n setCountryCode(\n data.selection?.countryCode?.toUpperCase() ?? fallbackCountryCode,\n );\n setSourceCurrencyCode((current) => {\n const currencies = getFiatCurrencyOptions(data);\n if (\n current &&\n currencies.some((currency) => currency.currencyCode === current)\n ) {\n return current;\n }\n return getDefaultFiatCurrencyCode(data);\n });\n },\n [],\n );\n\n const loadOptions = React.useCallback(\n async (signal?: AbortSignal) => {\n setOptionsLoading(true);\n setError(null);\n try {\n const loadOptionsForCountry = async (countryCodeToLoad: string) => {\n const requestedCountryCode = countryCodeToLoad.toUpperCase();\n const cached = readCachedOnrampOptions(baseUrl, requestedCountryCode);\n if (cached) {\n cacheOnrampProviders(cached.providers);\n cacheOnrampFiatMetadata(\n cached.selection?.fiatCurrencyMetadata ??\n cached.fiatCurrencyMetadata,\n );\n logOnramp(\"options.cache_hit\", { requestedCountryCode });\n applyOptions(cached, requestedCountryCode);\n }\n\n try {\n const data = await fetchOnrampJson(\n baseUrl,\n `/api/v1/onramp/options?countryCode=${encodeURIComponent(\n requestedCountryCode,\n )}`,\n { method: \"GET\", signal },\n );\n cacheOnrampProviders(data.providers);\n cacheOnrampFiatMetadata(\n data.selection?.fiatCurrencyMetadata ?? data.fiatCurrencyMetadata,\n );\n cacheOnrampPaymentMethods(\n data.selection?.paymentMethods ??\n data.paymentMethods ??\n data.paymentMethodMetadata,\n );\n writeCachedOnrampOptions(baseUrl, requestedCountryCode, data);\n\n const selectedCountryCode =\n data.selection?.countryCode?.toUpperCase();\n if (\n selectedCountryCode &&\n selectedCountryCode !== requestedCountryCode &&\n isCountryInOptionsList(data, selectedCountryCode)\n ) {\n writeCachedOnrampOptions(baseUrl, selectedCountryCode, data);\n }\n\n return { data, requestedCountryCode };\n } catch (fetchError) {\n if (cached) {\n logOnramp(\"options.refresh_failed_using_cache\", {\n error: fetchError,\n requestedCountryCode,\n });\n return { data: cached, requestedCountryCode };\n }\n throw fetchError;\n }\n };\n\n const resolvedCountryCode =\n userSelectedCountryRef.current ||\n (await resolveOnrampCountryCode(signal));\n signal?.throwIfAborted();\n logOnramp(\"country.resolved\", { countryCode: resolvedCountryCode });\n let { data, requestedCountryCode } =\n await loadOptionsForCountry(resolvedCountryCode);\n\n if (!isCountryInOptionsList(data, requestedCountryCode)) {\n const fallbackCountryCode =\n getUnsupportedCountryFallbackCode(baseUrl);\n if (fallbackCountryCode !== requestedCountryCode) {\n const fallbackOptions =\n await loadOptionsForCountry(fallbackCountryCode);\n data = fallbackOptions.data;\n requestedCountryCode = fallbackOptions.requestedCountryCode;\n }\n }\n\n signal?.throwIfAborted();\n applyOptions(data, requestedCountryCode);\n } catch (requestError) {\n if (signal?.aborted) return;\n const message = getErrorMessage(requestError);\n setError(message);\n onErrorRef.current?.(message);\n } finally {\n if (!signal?.aborted) setOptionsLoading(false);\n }\n },\n [applyOptions, baseUrl],\n );\n\n React.useEffect(() => {\n let controller: AbortController | null = new AbortController();\n void loadOptions(controller.signal);\n\n let lastComebackAt = Date.now();\n const handleComeback = () => {\n if (\n typeof document !== \"undefined\" &&\n document.visibilityState === \"hidden\"\n )\n return;\n const now = Date.now();\n if (now - lastComebackAt < 3000) return;\n lastComebackAt = now;\n controller?.abort();\n controller = new AbortController();\n void loadOptions(controller.signal);\n };\n\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"focus\", handleComeback);\n }\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"visibilitychange\", handleComeback);\n }\n\n return () => {\n controller?.abort();\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"focus\", handleComeback);\n }\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"visibilitychange\", handleComeback);\n }\n };\n }, [loadOptions]);\n\n const getRequestErrorMessage = React.useCallback(\n (requestError: unknown) =>\n getOnrampRequestErrorMessage(requestError, {\n countryCode,\n sourceCurrencyCode,\n token: toToken,\n }),\n [countryCode, sourceCurrencyCode, toToken],\n );\n\n React.useEffect(() => {\n setBlockedRateRequest((current) =>\n current && current.key !== rateRequestKey ? null : current,\n );\n }, [rateRequestKey]);\n\n React.useEffect(() => {\n setFailedQuoteRequest((current) =>\n current && current.key !== quoteRequestKey ? null : current,\n );\n }, [quoteRequestKey]);\n\n React.useEffect(() => {\n if (activeSheet !== \"country\") setCountrySearch(\"\");\n if (activeSheet !== \"currency\") setCurrencySearch(\"\");\n if (activeSheet !== \"method\") setMethodSearch(\"\");\n if (activeSheet !== \"partner\") setPartnerSearch(\"\");\n }, [activeSheet]);\n\n React.useEffect(() => {\n quotesLoadingRef.current = quotesLoading;\n }, [quotesLoading]);\n\n React.useEffect(() => {\n let cancelled = false;\n const controller = new AbortController();\n const loadForex = async () => {\n const rates = await fetchOnrampForexRates(controller.signal);\n if (!cancelled && rates && Object.keys(rates).length > 0) {\n setForexRates(rates);\n }\n };\n void loadForex();\n return () => {\n controller.abort();\n cancelled = true;\n };\n }, []);\n\n React.useEffect(() => {\n if (blockedRateRequest?.key === rateRequestKey) {\n quoteRunIdRef.current += 1;\n lastRouteRequestKeyRef.current = rateRequestKey;\n lastQuoteRequestKeyRef.current = \"\";\n setRoutes([]);\n setSelectedPaymentMethod(\"\");\n setQuotes([]);\n setSelectedProvider(\"\");\n setError(blockedRateRequest.message);\n setRoutesLoading(false);\n setQuotesLoading(false);\n return;\n }\n if (isDestinationTokenUnsupported) {\n quoteRunIdRef.current += 1;\n lastRouteRequestKeyRef.current = \"\";\n lastQuoteRequestKeyRef.current = \"\";\n setRoutes([]);\n setSelectedPaymentMethod(\"\");\n setQuotes([]);\n setSelectedProvider(\"\");\n setError(null);\n setRoutesLoading(false);\n setQuotesLoading(false);\n return;\n }\n if (\n !countryCode ||\n !sourceCurrencyCode ||\n !destinationRequestDetails.destinationCurrencyCode\n ) {\n lastRouteRequestKeyRef.current = \"\";\n lastQuoteRequestKeyRef.current = \"\";\n setRoutes([]);\n setSelectedPaymentMethod(\"\");\n setQuotes([]);\n setSelectedProvider(\"\");\n setRoutesLoading(false);\n setQuotesLoading(false);\n return;\n }\n if (lastRouteRequestKeyRef.current === rateRequestKey) return;\n const routeRunId = routeRunIdRef.current + 1;\n routeRunIdRef.current = routeRunId;\n quoteRunIdRef.current += 1;\n lastQuoteRequestKeyRef.current = \"\";\n setRoutes([]);\n setSelectedPaymentMethod(\"\");\n setQuotes([]);\n setSelectedProvider(\"\");\n let cancelled = false;\n const controller = new AbortController();\n\n const loadRoutes = async () => {\n setRoutesLoading(true);\n setError(null);\n try {\n const params = new URLSearchParams({\n countryCode,\n destinationCurrencyCode:\n destinationRequestDetails.destinationCurrencyCode,\n sourceCurrencyCode,\n });\n if (destinationRequestDetails.destinationChainId) {\n params.set(\n \"destinationChainId\",\n destinationRequestDetails.destinationChainId,\n );\n }\n if (destinationRequestDetails.destinationToken) {\n params.set(\n \"destinationToken\",\n destinationRequestDetails.destinationToken,\n );\n }\n const data = await fetchOnrampJson(\n baseUrl,\n `/api/v1/onramp/routes?${params.toString()}`,\n { method: \"GET\", signal: controller.signal },\n );\n if (cancelled || routeRunIdRef.current !== routeRunId) return;\n const nextRoutes: OnrampRoute[] = (\n Array.isArray(data) ? data : (data.routes ?? [])\n ).map((route: any) => ({\n ...route,\n provider: route.provider ?? route.partner,\n paymentMethods: route.paymentMethods?.map((method: any) => ({\n ...method,\n method: method.method ?? method.name,\n })),\n }));\n for (const route of nextRoutes) {\n cacheOnrampPaymentMethods(route.paymentMethods);\n }\n setRoutes(nextRoutes);\n const firstRoute = nextRoutes[0];\n setSelectedProvider(firstRoute?.provider ?? \"\");\n setSelectedPaymentMethod(firstRoute?.paymentMethods?.[0]?.method ?? \"\");\n lastRouteRequestKeyRef.current = rateRequestKey;\n } catch (requestError) {\n if (cancelled || routeRunIdRef.current !== routeRunId) return;\n const message = getRequestErrorMessage(requestError);\n quoteRunIdRef.current += 1;\n if (isTerminalOnrampRateError(requestError)) {\n setBlockedRateRequest({ key: rateRequestKey, message });\n }\n setRoutes([]);\n setSelectedPaymentMethod(\"\");\n setQuotes([]);\n setSelectedProvider(\"\");\n setError(message);\n onErrorRef.current?.(message);\n } finally {\n if (!cancelled && routeRunIdRef.current === routeRunId) {\n setRoutesLoading(false);\n }\n }\n };\n\n void loadRoutes();\n return () => {\n controller.abort();\n cancelled = true;\n };\n }, [\n baseUrl,\n blockedRateRequest?.key,\n blockedRateRequest?.message,\n countryCode,\n destinationRequestDetails.destinationChainId,\n destinationRequestDetails.destinationCurrencyCode,\n destinationRequestDetails.destinationToken,\n getRequestErrorMessage,\n isDestinationTokenUnsupported,\n rateRequestKey,\n sourceCurrencyCode,\n ]);\n\n const fetchQuotes = React.useCallback(async () => {\n if (\n !countryCode ||\n !sourceCurrencyCode ||\n !destinationRequestDetails.destinationCurrencyCode ||\n !selectedPaymentMethod ||\n !parsedSourceAmount?.gt(0) ||\n amountLimitMessage ||\n isDestinationTokenUnsupported\n ) {\n return;\n }\n if (blockedRateRequest?.key === rateRequestKey) {\n setError(blockedRateRequest.message);\n setQuotesLoading(false);\n return;\n }\n\n quoteAbortRef.current?.abort();\n const controller = new AbortController();\n quoteAbortRef.current = controller;\n const runId = quoteRunIdRef.current + 1;\n quoteRunIdRef.current = runId;\n setQuotesLoading(true);\n setFailedQuoteRequest(null);\n setError(null);\n try {\n const data = await fetchOnrampJson(\n baseUrl,\n \"/api/v1/onramp/quote\",\n {\n body: JSON.stringify({\n countryCode,\n destination: {\n chainId: destinationRequestDetails.destinationChainId,\n currencyCode: destinationRequestDetails.destinationCurrencyCode,\n token: destinationRequestDetails.destinationToken,\n },\n destinationChainId: destinationRequestDetails.destinationChainId,\n destinationCurrencyCode:\n destinationRequestDetails.destinationCurrencyCode,\n destinationToken: destinationRequestDetails.destinationToken,\n paymentMethodType: selectedPaymentMethod,\n sourceAmount,\n sourceCurrencyCode,\n walletAddress: quoteWalletAddress,\n }),\n method: \"POST\",\n signal: controller.signal,\n },\n );\n if (controller.signal.aborted || quoteRunIdRef.current !== runId) return;\n const nextQuotes = sortQuotes(\n (data.quotes ?? []).map((quote: any) => ({\n ...quote,\n provider: quote.provider ?? quote.serviceProvider,\n destinationAmount: String(quote.destinationAmount),\n sourceAmount: String(quote.sourceAmount),\n rampScore: quote.rampScore ?? quote.rampIntelligence?.rampScore,\n lowKyc: quote.lowKyc ?? quote.rampIntelligence?.lowKyc,\n fees: quote.fees ?? {\n total: quote.totalFee,\n network: quote.networkFee,\n provider: quote.transactionFee,\n partner: quote.partnerFee,\n },\n })),\n );\n setQuotesRequestKey(quoteRequestKey);\n setQuotes(nextQuotes);\n setSelectedProvider(nextQuotes[0]?.provider ?? \"\");\n if (nextQuotes.length === 0) {\n setError(\n \"No local currency rates are available for this token and currency. Choose another deposit token or pay with wallet.\",\n );\n }\n } catch (requestError) {\n if (controller.signal.aborted || quoteRunIdRef.current !== runId) return;\n const isTerminalError = isTerminalOnrampRateError(requestError);\n const message = isTerminalError\n ? getRequestErrorMessage(requestError)\n : ONRAMP_GENERIC_QUOTE_ERROR_MESSAGE;\n if (isTerminalError) {\n setBlockedRateRequest({ key: rateRequestKey, message });\n }\n setFailedQuoteRequest({ key: quoteRequestKey, message });\n setQuotesRequestKey(\"\");\n setQuotes([]);\n setError(message);\n onErrorRef.current?.(message);\n } finally {\n if (quoteRunIdRef.current === runId) {\n setQuotesLoading(false);\n setQuoteRefreshSeconds(QUOTE_REFRESH_SECONDS);\n }\n }\n }, [\n amountLimitMessage,\n baseUrl,\n countryCode,\n destinationRequestDetails.destinationChainId,\n destinationRequestDetails.destinationCurrencyCode,\n destinationRequestDetails.destinationToken,\n getRequestErrorMessage,\n blockedRateRequest,\n isDestinationTokenUnsupported,\n parsedSourceAmount,\n quoteRequestKey,\n quoteWalletAddress,\n rateRequestKey,\n selectedPaymentMethod,\n sourceAmount,\n sourceCurrencyCode,\n ]);\n\n React.useEffect(() => {\n if (session?.sessionId) return;\n if (\n !sourceCurrencyCode ||\n !destinationRequestDetails.destinationCurrencyCode ||\n !selectedPaymentMethod ||\n !parsedSourceAmount?.gt(0) ||\n amountLimitMessage ||\n isDestinationTokenUnsupported\n ) {\n lastQuoteRequestKeyRef.current = \"\";\n setQuotesRequestKey(\"\");\n setQuotes([]);\n return;\n }\n if (failedQuoteRequest?.key === quoteRequestKey) {\n lastQuoteRequestKeyRef.current = quoteRequestKey;\n setError(failedQuoteRequest.message);\n setQuotesLoading(false);\n return;\n }\n if (lastQuoteRequestKeyRef.current === quoteRequestKey) return;\n setQuotes([]);\n const timer = window.setTimeout(() => {\n lastQuoteRequestKeyRef.current = quoteRequestKey;\n void fetchQuotes();\n }, 350);\n return () => {\n window.clearTimeout(timer);\n };\n }, [\n amountLimitMessage,\n destinationRequestDetails.destinationChainId,\n destinationRequestDetails.destinationCurrencyCode,\n destinationRequestDetails.destinationToken,\n fetchQuotes,\n failedQuoteRequest,\n isDestinationTokenUnsupported,\n parsedSourceAmount,\n quoteRequestKey,\n selectedPaymentMethod,\n session?.sessionId,\n sourceCurrencyCode,\n ]);\n\n React.useEffect(() => {\n if (session?.sessionId || !selectedQuote || sessionLoading) {\n setQuoteRefreshSeconds(0);\n setQuoteRefreshProgress(0);\n return;\n }\n let cycleStartedAt = Date.now();\n\n const updateRefreshCountdown = () => {\n const elapsed = Date.now() - cycleStartedAt;\n const remainingMs = Math.max(0, QUOTE_REFRESH_MS - elapsed);\n setQuoteRefreshSeconds(Math.ceil(remainingMs / 1000));\n setQuoteRefreshProgress(remainingMs / QUOTE_REFRESH_MS);\n\n if (remainingMs > 0 || quotesLoadingRef.current) return;\n cycleStartedAt = Date.now();\n setQuoteRefreshSeconds(QUOTE_REFRESH_SECONDS);\n setQuoteRefreshProgress(1);\n void fetchQuotes();\n };\n\n setQuoteRefreshSeconds(QUOTE_REFRESH_SECONDS);\n setQuoteRefreshProgress(1);\n updateRefreshCountdown();\n const interval = window.setInterval(() => {\n updateRefreshCountdown();\n }, 250);\n return () => {\n window.clearInterval(interval);\n };\n }, [fetchQuotes, selectedQuote, session?.sessionId, sessionLoading]);\n\n React.useEffect(() => {\n if (session?.sessionId && sessionHistoryRef.current) {\n sessionUpdateRef.current?.({ ...sessionHistoryRef.current, session });\n }\n }, [session]);\n\n React.useEffect(() => {\n const derivedSessionState =\n depositExecution.status === \"running\"\n ? \"COMPLETING_DEPOSIT\"\n : depositExecution.status === \"success\"\n ? \"DEPOSIT_SUCCESS\"\n : depositExecution.status === \"failed\"\n ? \"DEPOSIT_FAILED\"\n : normalizedSessionState ||\n (sessionCallbackReceived\n ? \"ONRAMP_CALLBACK_RECEIVED\"\n : \"AWAITING_USER\");\n logOnramp(\"ui.state\", {\n sessionId: session?.sessionId,\n paymentState: normalizedSessionState,\n depositState: depositExecution.status,\n derivedSessionState,\n });\n onSessionStateChange?.(session?.sessionId ? derivedSessionState : null);\n }, [\n depositExecution.status,\n normalizedSessionState,\n onSessionStateChange,\n sessionCallbackReceived,\n session?.sessionId,\n ]);\n\n React.useEffect(\n () => () => {\n onSessionStateChange?.(null);\n },\n [onSessionStateChange],\n );\n\n const applyOnrampCallback = React.useCallback((payload: unknown) => {\n const currentId = sessionRef.current?.sessionId;\n if (!currentId) return;\n if (\n payload !== ONRAMP_CALLBACK_SUCCESS_MESSAGE &&\n (!isOnrampCallbackPayload(payload) || payload.sessionId !== currentId)\n )\n return;\n // Redirects/postMessages only wake the authoritative status check.\n logOnramp(\"provider.return\", { sessionId: currentId });\n setSessionCallbackReceived(true);\n setError(null);\n refreshSessionRef.current?.();\n }, []);\n\n const applyManualOnrampSessionId = React.useCallback(\n (sessionId: string) => {\n const normalizedSessionId = sessionId.trim();\n if (!normalizedSessionId) return;\n if (depositBusyRef.current || pendingDepositRef.current) return;\n logOnramp(\"session.manual_resume\", { sessionId: normalizedSessionId });\n sessionHistoryRef.current = {\n ownerAddress: ownerRef.current ?? persistedOwnerAddress ?? \"\",\n context: { chainId: toToken?.chainId, tokenSymbol: toToken?.symbol },\n };\n sessionQuoteRef.current = null;\n setSessionCallbackReceived(true);\n setSession({\n sessionId: normalizedSessionId,\n state: \"AWAITING_USER\",\n });\n setError(null);\n },\n [persistedOwnerAddress, toToken?.chainId, toToken?.symbol],\n );\n\n React.useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const handleMessage = (event: MessageEvent) => {\n if (\n event.origin !==\n new URL(getOnrampReturnUrl(), window.location.href).origin\n )\n return;\n if (event.data === ONRAMP_CALLBACK_SUCCESS_MESSAGE) {\n try {\n (event.source as Window | null)?.postMessage(\n ONRAMP_CALLBACK_SUCCESS_ACK_MESSAGE,\n event.origin,\n );\n } catch {\n // The callback page will close itself if the ack cannot be sent.\n }\n }\n applyOnrampCallback(event.data);\n };\n const handleStorage = (event: StorageEvent) => {\n if (event.key !== ONRAMP_CALLBACK_STORAGE_KEY || !event.newValue) return;\n try {\n applyOnrampCallback(JSON.parse(event.newValue));\n } catch {\n // Ignore malformed callback payloads from storage.\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n window.addEventListener(\"storage\", handleStorage);\n window.setRampSessionId = applyManualOnrampSessionId;\n\n let channel: BroadcastChannel | null = null;\n if (\"BroadcastChannel\" in window) {\n channel = new BroadcastChannel(ONRAMP_CALLBACK_CHANNEL);\n channel.onmessage = (event) => applyOnrampCallback(event.data);\n }\n\n return () => {\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"storage\", handleStorage);\n if (window.setRampSessionId === applyManualOnrampSessionId) {\n delete window.setRampSessionId;\n }\n channel?.close();\n };\n }, [applyManualOnrampSessionId, applyOnrampCallback]);\n\n const paymentTerminal = isOnrampTerminalState(normalizedSessionState);\n React.useEffect(() => {\n const sessionId = session?.sessionId;\n if (!sessionId || paymentTerminal) return;\n let previousState = sessionRef.current?.state;\n const startedAt = Date.now();\n logOnramp(\"poll.start\", {\n sessionId,\n baseUrl,\n intervalMs: ONRAMP_SESSION_POLL_MS,\n });\n const poller = startOnrampPolling({\n fetchSession: (signal) =>\n fetchOnrampJson(\n baseUrl,\n `/api/v1/onramp/sessions/${encodeURIComponent(sessionId)}`,\n { method: \"GET\", signal },\n ),\n onData: (payload) => {\n const data = normalizeOnrampSession(payload, sessionId);\n const terminal = isOnrampTerminalState(data.state);\n logOnramp(\"poll.status\", {\n sessionId,\n previousState,\n state: data.state,\n rawMeldStatus: data.rawMeldStatus,\n transaction: data.transaction,\n providerUpdatedAt: data.updatedAt,\n elapsedMs: Date.now() - startedAt,\n terminal,\n });\n previousState = data.state;\n setSession((current) =>\n current?.sessionId === sessionId\n ? mergeOnrampSession(current, data)\n : current,\n );\n setError(null);\n return terminal;\n },\n onError: (requestError) => {\n logOnramp(\"poll.retry\", { sessionId, error: requestError });\n setError(\n \"Unable to refresh payment status. Retrying automatically; keep this page open.\",\n );\n },\n intervalMs: ONRAMP_SESSION_POLL_MS,\n });\n refreshSessionRef.current = poller.refresh;\n const refresh = () => {\n if (document.visibilityState === \"hidden\") return;\n logOnramp(\"poll.wake\", { sessionId });\n void poller.refresh();\n };\n window.addEventListener(\"focus\", refresh);\n window.addEventListener(\"online\", refresh);\n document.addEventListener(\"visibilitychange\", refresh);\n return () => {\n poller.stop();\n if (refreshSessionRef.current === poller.refresh)\n refreshSessionRef.current = null;\n window.removeEventListener(\"focus\", refresh);\n window.removeEventListener(\"online\", refresh);\n document.removeEventListener(\"visibilitychange\", refresh);\n logOnramp(\"poll.stop\", { sessionId, elapsedMs: Date.now() - startedAt });\n };\n }, [baseUrl, paymentTerminal, session?.sessionId]);\n\n React.useEffect(() => {\n logOnramp(\"flow.mounted\", {\n baseUrl,\n environment: getOnrampRuntimeEnvironment(baseUrl),\n });\n return () => {\n depositAbortRef.current?.abort();\n quoteAbortRef.current?.abort();\n createSessionAbortRef.current?.abort();\n quoteRunIdRef.current += 1;\n routeRunIdRef.current += 1;\n logOnramp(\"flow.cleanup\", {\n sessionId: sessionRef.current?.sessionId,\n pending: pendingDepositRef.current,\n });\n };\n }, [baseUrl]);\n\n React.useEffect(() => {\n if (!session?.sessionId) {\n depositExecutionSessionRef.current = \"\";\n setDepositExecution({ status: \"idle\" });\n return;\n }\n if (\n depositExecutionSessionRef.current &&\n depositExecutionSessionRef.current !== session.sessionId\n ) {\n depositExecutionSessionRef.current = \"\";\n setDepositExecution({ status: \"idle\" });\n }\n }, [session?.sessionId]);\n\n React.useEffect(() => {\n if (\n !session?.sessionId ||\n normalizedSessionState !== \"SETTLED\" ||\n !hasConnectedWallet ||\n depositExecution.status !== \"idle\"\n ) {\n return;\n }\n void executeOnrampDeposit();\n }, [\n depositExecution.status,\n hasConnectedWallet,\n executeOnrampDeposit,\n normalizedSessionState,\n session?.sessionId,\n ]);\n\n const createSession = async () => {\n if (\n !selectedQuote ||\n !hasConnectedWallet ||\n !ownerAddress ||\n !selectedPaymentMethod ||\n isDestinationTokenUnsupported\n ) {\n return;\n }\n if (\n sessionLoading ||\n depositBusyRef.current ||\n createSessionAbortRef.current\n )\n return;\n const controller = new AbortController();\n createSessionAbortRef.current = controller;\n setSessionLoading(true);\n setError(null);\n setSessionCallbackReceived(false);\n depositExecutionSessionRef.current = \"\";\n setDepositExecution({ status: \"idle\" });\n quoteAbortRef.current?.abort();\n quoteRunIdRef.current += 1;\n const providerWindow = openOnrampProviderWindow();\n if (!providerWindow) {\n createSessionAbortRef.current = null;\n setSessionLoading(false);\n setError(\n \"Payment provider popup was blocked. Allow popups and try again.\",\n );\n return;\n }\n try {\n const liveAccount = await checkWalletConnection();\n controller.signal.throwIfAborted();\n if (liveAccount?.toLowerCase() !== ownerAddress.toLowerCase()) {\n providerWindow.close();\n setError(\n \"Connect your wallet and wait for a refreshed quote before paying.\",\n );\n return;\n }\n logOnramp(\"session.create\", {\n baseUrl,\n environment: getOnrampRuntimeEnvironment(baseUrl),\n provider: selectedQuote.provider,\n destination: destinationRequestDetails,\n ownerAddress,\n returnUrl: getOnrampReturnUrl(),\n });\n const data = await fetchOnrampJson(\n baseUrl,\n \"/api/v1/onramp/sessions\",\n {\n body: JSON.stringify({\n countryCode,\n destination: {\n chainId: destinationRequestDetails.destinationChainId,\n currencyCode:\n selectedQuote.destinationCurrencyCode ??\n destinationRequestDetails.destinationCurrencyCode,\n token: destinationRequestDetails.destinationToken,\n },\n destinationChainId: destinationRequestDetails.destinationChainId,\n destinationCurrencyCode:\n selectedQuote.destinationCurrencyCode ??\n destinationRequestDetails.destinationCurrencyCode,\n destinationToken: destinationRequestDetails.destinationToken,\n paymentMethodType: selectedPaymentMethod,\n provider: selectedQuote.provider,\n returnUrl: getOnrampReturnUrl(),\n sourceAmount: selectedQuote.sourceAmount,\n sourceCurrencyCode: selectedQuote.sourceCurrencyCode,\n walletAddress: ownerAddress,\n }),\n headers: {\n \"Idempotency-Key\": createIdempotencyKey(),\n },\n method: \"POST\",\n signal: controller.signal,\n },\n );\n controller.signal.throwIfAborted();\n const normalized = normalizeOnrampSession(data);\n if (!normalized.sessionId)\n throw new Error(\n \"Payment session ID was not returned. Unable to track this payment.\",\n );\n sessionHistoryRef.current = {\n ownerAddress,\n context: {\n chainId: toToken?.chainId,\n tokenSymbol: toToken?.symbol,\n destinationAmount: selectedQuote.destinationAmount,\n sourceAmount: selectedQuote.sourceAmount,\n sourceCurrencyCode: selectedQuote.sourceCurrencyCode,\n provider: selectedQuote.provider,\n paymentMethodType: selectedPaymentMethod,\n },\n };\n sessionQuoteRef.current = selectedQuote;\n // Save before navigating the provider window so pending purchases survive closing the widget.\n sessionUpdateRef.current?.({\n ...sessionHistoryRef.current,\n session: normalized,\n });\n setSession(normalized);\n pendingApprovalRef.current = null;\n remainingDepositRef.current = null;\n logOnramp(\"session.created\", normalized);\n const widgetUrl = normalized.widgetUrl ?? normalized.fallbackWidgetUrl;\n if (widgetUrl) {\n logOnramp(\"provider.open\", {\n sessionId: normalized.sessionId,\n origin: new URL(widgetUrl).origin,\n });\n providerWindow.location.href = widgetUrl;\n } else {\n providerWindow.close();\n setError(\"Payment provider URL was not returned. Try again.\");\n }\n } catch (requestError) {\n providerWindow?.close();\n if (controller.signal.aborted) return;\n const message = getRequestErrorMessage(requestError);\n setError(message);\n onErrorRef.current?.(message);\n } finally {\n if (!controller.signal.aborted) setSessionLoading(false);\n if (createSessionAbortRef.current === controller)\n createSessionAbortRef.current = null;\n }\n };\n\n const handlePrimaryAction = async () => {\n if (!hasConnectedWallet) {\n await reconnectWallet();\n return;\n }\n await createSession();\n };\n\n const reconnectWallet = async () => {\n if (walletActionPending) return;\n setWalletActionPending(true);\n setError(null);\n logOnramp(\"wallet.connect_requested\", { sessionId: session?.sessionId });\n try {\n await onConnectWallet();\n await checkWalletConnection();\n } catch (connectionError) {\n const message = getErrorMessage(connectionError);\n setError(message);\n onErrorRef.current?.(message);\n } finally {\n setWalletActionPending(false);\n }\n };\n\n const resetSession = () => {\n if (depositBusyRef.current) return;\n logOnramp(\"session.reset\", { sessionId: session?.sessionId });\n pendingDepositRef.current = null;\n remainingDepositRef.current = null;\n pendingApprovalRef.current = null;\n setError(null);\n setSessionCallbackReceived(false);\n depositExecutionSessionRef.current = \"\";\n setDepositExecution({ status: \"idle\" });\n setSession(null);\n };\n\n const completeSession = () => {\n if (depositBusyRef.current) return;\n logOnramp(\"session.done\", {\n sessionId: session?.sessionId,\n depositExecution,\n });\n pendingDepositRef.current = null;\n remainingDepositRef.current = null;\n pendingApprovalRef.current = null;\n setError(null);\n setSessionCallbackReceived(false);\n depositExecutionSessionRef.current = \"\";\n setDepositExecution({ status: \"idle\" });\n setQuotes([]);\n setSelectedProvider(\"\");\n setSession(null);\n setSourceAmount(\"\");\n };\n\n const handleCountrySelect = React.useCallback(\n async (nextCountryCode: string) => {\n const normalizedCountryCode = nextCountryCode.toUpperCase();\n if (!normalizedCountryCode) return;\n setActiveSheet(null);\n if (normalizedCountryCode === countryCode.toUpperCase()) return;\n\n logOnramp(\"selection.country\", { countryCode: normalizedCountryCode });\n userSelectedCountryRef.current = normalizedCountryCode;\n writeOnrampCache(\n ONRAMP_USER_COUNTRY_CACHE_KEY,\n normalizedCountryCode,\n ONRAMP_USER_COUNTRY_CACHE_TTL_MS,\n );\n setCountryCode(normalizedCountryCode);\n\n const cached = readCachedOnrampOptions(baseUrl, normalizedCountryCode);\n if (cached) {\n cacheOnrampProviders(cached.providers);\n cacheOnrampFiatMetadata(\n cached.selection?.fiatCurrencyMetadata ??\n cached.fiatCurrencyMetadata,\n );\n setOptions(cached);\n const nextFiat = getDefaultFiatCurrencyCode(cached);\n setSourceCurrencyCode(nextFiat);\n }\n\n setSelectedPaymentMethod(\"\");\n setSelectedProvider(\"\");\n setQuotes([]);\n setRoutes([]);\n setBlockedRateRequest(null);\n setFailedQuoteRequest(null);\n setDepositExecution({ status: \"idle\" });\n setSession(null);\n setGasShortfallInfo(null);\n\n setOptionsLoading(true);\n try {\n const data = await fetchOnrampJson(\n baseUrl,\n `/api/v1/onramp/options?countryCode=${encodeURIComponent(\n normalizedCountryCode,\n )}`,\n );\n cacheOnrampProviders(data.providers);\n cacheOnrampFiatMetadata(\n data.selection?.fiatCurrencyMetadata ?? data.fiatCurrencyMetadata,\n );\n cacheOnrampPaymentMethods(\n data.selection?.paymentMethods ??\n data.paymentMethods ??\n data.paymentMethodMetadata,\n );\n writeCachedOnrampOptions(baseUrl, normalizedCountryCode, data);\n\n const selectedCode = data.selection?.countryCode?.toUpperCase();\n if (\n selectedCode &&\n selectedCode !== normalizedCountryCode &&\n isCountryInOptionsList(data, selectedCode)\n ) {\n writeCachedOnrampOptions(baseUrl, selectedCode, data);\n }\n\n setOptions(data);\n const mappedFiat = getDefaultFiatCurrencyCode(data);\n setSourceCurrencyCode(mappedFiat);\n } catch (fetchError) {\n if (!cached) {\n const message = getErrorMessage(fetchError);\n setError(message);\n onErrorRef.current?.(message);\n }\n } finally {\n setOptionsLoading(false);\n }\n },\n [baseUrl, countryCode],\n );\n\n const handleCurrencySelect = (currencyCode: string) => {\n logOnramp(\"selection.currency\", { currencyCode });\n setSourceCurrencyCode(currencyCode);\n setSelectedPaymentMethod(\"\");\n setSelectedProvider(\"\");\n setQuotes([]);\n setRoutes([]);\n setActiveSheet(null);\n };\n\n const handleDestinationTokenSelect = (token: SwapTokenOption) => {\n logOnramp(\"selection.destination\", {\n chainId: token.chainId,\n address: token.contractAddress,\n });\n if (!isSameOnrampToken(token, toToken)) {\n onSelectDestinationToken?.(token);\n setSelectedPaymentMethod(\"\");\n setSelectedProvider(\"\");\n setQuotes([]);\n setRoutes([]);\n setSessionCallbackReceived(false);\n setSession(null);\n }\n setActiveSheet(null);\n };\n\n const handleProviderSelect = (option: OnrampProviderOption) => {\n logOnramp(\"selection.provider\", {\n provider: option.provider,\n paymentMethod: option.paymentMethodType,\n });\n setSelectedProvider(option.provider);\n if (option.paymentMethodType) {\n setSelectedPaymentMethod(option.paymentMethodType);\n }\n if (!option.quote) {\n setQuotes([]);\n }\n setActiveSheet(null);\n };\n\n const handleMethodSelect = (method: string) => {\n const nextRoute =\n routes.find(\n (route) =>\n route.provider === selectedProvider &&\n route.paymentMethods?.some(\n (candidate) => candidate.method === method,\n ),\n ) ??\n routes.find((route) =>\n route.paymentMethods?.some((candidate) => candidate.method === method),\n );\n setSelectedPaymentMethod(method);\n setSelectedProvider(nextRoute?.provider ?? selectedProvider);\n setQuotes([]);\n setActiveSheet(null);\n };\n\n const receiveAmount = selectedQuote?.destinationAmount;\n const receiveUsd = selectedQuote?.destinationAmount;\n const feeTotal = selectedQuote?.fees?.total;\n const displayProvider = selectedQuote?.provider ?? selectedProvider;\n const providerSubtitle = selectedQuote ? \"Best available quote\" : \"\";\n\n const receiveFiatSubtitle = React.useMemo(() => {\n if (!receiveAmount) return \"$0.00 USD\";\n const usdDisplay = formatUsdDisplay(receiveUsd);\n const upperCurrency = sourceCurrencyCode.toUpperCase();\n if (!upperCurrency || upperCurrency === \"USD\") {\n return usdDisplay;\n }\n\n // Try converting USD to selected fiat currency using live forex rate\n let fiatAmount: Decimal | null = null;\n const rate = forexRates[upperCurrency];\n if (rate && typeof rate === \"number\" && rate > 0) {\n const parsedUsd = parseDecimal(receiveUsd);\n if (parsedUsd) {\n fiatAmount = parsedUsd.mul(rate);\n }\n }\n\n // Fallback: estimate from quote (sourceAmount minus fees)\n if (!fiatAmount && selectedQuote?.sourceAmount) {\n const sourceDec = parseDecimal(selectedQuote.sourceAmount);\n const feeDec = parseDecimal(selectedQuote.fees?.total) ?? new Decimal(0);\n if (sourceDec && sourceDec.gt(0)) {\n fiatAmount = Decimal.max(0, sourceDec.minus(feeDec));\n }\n }\n\n if (fiatAmount && fiatAmount.gt(0)) {\n const formattedFiat = formatCurrencyAmount(fiatAmount, upperCurrency, 2);\n return `${usdDisplay} ≈ ${formattedFiat}`;\n }\n\n return usdDisplay;\n }, [\n forexRates,\n receiveAmount,\n receiveUsd,\n selectedQuote?.fees?.total,\n selectedQuote?.sourceAmount,\n sourceCurrencyCode,\n ]);\n\n const tokenCostFiatValue = React.useMemo(() => {\n if (!receiveAmount) return null;\n if (selectedQuote?.sourceAmount) {\n const sourceDec = parseDecimal(selectedQuote.sourceAmount);\n const feeDec = parseDecimal(selectedQuote.fees?.total) ?? new Decimal(0);\n if (sourceDec && sourceDec.gt(0)) {\n return Decimal.max(0, sourceDec.minus(feeDec));\n }\n }\n\n const upperCurrency = sourceCurrencyCode.toUpperCase();\n const parsedUsd = parseDecimal(receiveUsd);\n if (!parsedUsd || parsedUsd.lte(0)) return null;\n\n if (!upperCurrency || upperCurrency === \"USD\") {\n return parsedUsd;\n }\n\n const rate = forexRates[upperCurrency];\n if (rate && typeof rate === \"number\" && rate > 0) {\n return parsedUsd.mul(rate);\n }\n\n return null;\n }, [\n forexRates,\n receiveAmount,\n receiveUsd,\n selectedQuote?.fees?.total,\n selectedQuote?.sourceAmount,\n sourceCurrencyCode,\n ]);\n\n const activeQuoteRequestFailure =\n failedQuoteRequest?.key === quoteRequestKey ? failedQuoteRequest : null;\n const hasRouteDetails = Boolean(\n selectedPaymentMethodDetails || selectedPaymentMethod || displayProvider,\n );\n const rateRequestLoading = routesLoading || quotesLoading;\n const fetchingBestRates =\n hasPositiveSourceAmount &&\n !selectedQuote &&\n !amountLimitMessage &&\n !error &&\n !activeQuoteRequestFailure &&\n !destinationTokenUnsupportedMessage &&\n Boolean(destinationRequestDetails.destinationCurrencyCode) &&\n (rateRequestLoading || Boolean(selectedPaymentMethod));\n const ctaRateLoading =\n !error &&\n !activeQuoteRequestFailure &&\n !destinationTokenUnsupportedMessage &&\n !selectedQuote &&\n (fetchingBestRates || (hasPositiveSourceAmount && rateRequestLoading));\n const quoteDetailsLoading =\n fetchingBestRates || (routesLoading && !hasRouteDetails);\n const shouldShowQuoteDetails =\n !destinationTokenUnsupportedMessage &&\n (quoteDetailsLoading || hasRouteDetails || Boolean(selectedQuote));\n const shouldShowQuoteTimer = Boolean(selectedQuote);\n const ctaDisabled =\n !hasPositiveSourceAmount ||\n !selectedQuote ||\n Boolean(destinationTokenUnsupportedMessage) ||\n Boolean(amountLimitMessage) ||\n ctaRateLoading ||\n sessionLoading ||\n walletActionPending ||\n (!hasConnectedWallet && walletChecking);\n\n if (session?.sessionId) {\n return (\n <>\n {error && (\n \n {error}\n \n )}\n {normalizedSessionState === \"TWO_FA_REQUIRED\" && (\n \n Complete the verification in the payment provider window to\n continue.\n \n )}\n void reconnectWallet()}\n depositExecution={depositExecution}\n gasShortfallInfo={gasShortfallInfo}\n onCancel={resetSession}\n onDone={completeSession}\n onRetryDeposit={() => void executeOnrampDeposit(true)}\n onRetryPayment={resetSession}\n opportunity={opportunity}\n primaryButtonForeground={primaryButtonForeground}\n quote={sessionQuoteRef.current ?? selectedQuote}\n session={session}\n sessionCallbackReceived={sessionCallbackReceived}\n sourceAmount={sourceAmount}\n sourceCurrencyCode={sourceCurrencyCode}\n toToken={toToken}\n />\n \n );\n }\n\n return (\n \n \n {shouldShowQuoteTimer && (\n \n {quotesLoading || routesLoading ? (\n \n ) : (\n \n )}\n {quotesLoading || routesLoading ? \"...\" : `${quoteRefreshSeconds}s`}\n \n )}\n\n \n setActiveSheet((prev) => (prev === \"country\" ? null : \"country\"))\n }\n style={{\n alignItems: \"center\",\n backgroundColor: theme.colors.surface,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: \"9px\",\n boxShadow: theme.shadows.iconButton,\n boxSizing: \"border-box\",\n cursor: \"pointer\",\n display: \"flex\",\n gap: \"6px\",\n height: \"32px\",\n justifyContent: \"center\",\n paddingInline: \"8px\",\n }}\n type=\"button\"\n >\n \n \n \n \n\n
\n \n \n \n
You Pay
\n \n setSourceAmount(normalizeAmountInput(event.target.value))\n }\n placeholder=\"0\"\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.colors.textStrong,\n fontFamily: theme.fonts.display,\n fontSize: \"31px\",\n fontWeight: 500,\n letterSpacing: \"0\",\n lineHeight: \"36px\",\n outline: \"none\",\n padding: 0,\n cursor: destinationTokenUnsupportedMessage\n ? \"not-allowed\"\n : undefined,\n width: \"100%\",\n }}\n value={sourceAmount}\n />\n \n {hasPositiveSourceAmount\n ? formatCurrencyAmount(\n selectedQuote?.sourceAmount ?? sourceAmount,\n selectedQuote?.sourceCurrencyCode ?? sourceCurrencyCode,\n )\n : \"Select currency\"}\n
\n \n setActiveSheet(\"currency\")}\n >\n \n \n {sourceCurrencyCode || \"---\"}\n \n \n \n\n {selectedPaymentMethodDetails?.limits && (\n \n \n \n Limits\n {selectedPaymentMethodDetails.limits.min\n ? ` · Min ${formatCurrencyAmount(\n selectedPaymentMethodDetails.limits.min,\n sourceCurrencyCode,\n )}`\n : \"\"}\n {selectedPaymentMethodDetails.limits.max\n ? ` · Max ${formatCurrencyAmount(\n selectedPaymentMethodDetails.limits.max,\n sourceCurrencyCode,\n )}`\n : \"\"}\n \n \n )}\n\n \n\n \n \n
Receive
\n \n {receiveAmount\n ? formatPlainNumberDisplay(receiveAmount, 6)\n : \"0\"}\n \n \n {receiveFiatSubtitle}\n \n \n setActiveSheet(\"destination\")}\n >\n \n \n {toToken?.symbol ?? \"Token\"}\n \n \n \n \n \n\n {shouldShowQuoteDetails &&\n (quoteDetailsLoading ? (\n \n ) : hasRouteDetails ? (\n
\n setActiveSheet(\"method\")}\n />\n }\n label=\"Payment Method\"\n >\n \n \n \n {selectedPaymentMethodDetails?.name ??\n getMethodLabel(selectedPaymentMethod)}\n
\n \n \n\n setActiveSheet(\"partner\")}\n />\n }\n divider\n label=\"Payment Partner\"\n >\n \n \n \n \n {getProviderLabel(displayProvider)}\n \n {providerSubtitle && (\n \n {providerSubtitle}\n \n )}\n \n \n \n\n {selectedQuote && (\n setActiveSheet(\"fees\")}\n style={{\n alignItems: \"center\",\n backgroundColor: \"transparent\",\n border: \"none\",\n borderTop: `1px solid ${theme.colors.divider}`,\n boxSizing: \"border-box\",\n cursor: \"pointer\",\n display: \"flex\",\n justifyContent: \"space-between\",\n padding: \"14px\",\n textAlign: \"left\",\n width: \"100%\",\n }}\n type=\"button\"\n >\n
\n \n Total Fees\n
\n \n Inclusive of fees\n \n \n \n \n {feeTotal\n ? formatCurrencyAmount(feeTotal, sourceCurrencyCode)\n : \"--\"}\n \n \n View breakdown\n \n \n \n )}\n \n ) : null)}\n\n {(destinationTokenUnsupportedMessage ||\n error ||\n amountLimitMessage ||\n session?.state) && (\n \n {destinationTokenUnsupportedMessage ??\n error ??\n amountLimitMessage ??\n `Onramp session ${session?.state?.toLowerCase() ?? \"created\"}.`}\n \n )}\n\n void handlePrimaryAction()}\n style={{\n alignItems: \"center\",\n backgroundColor: ctaDisabled ? theme.colors.surfaceCool : brand,\n border: \"none\",\n borderRadius: theme.radius.primaryButton,\n boxShadow: ctaDisabled ? \"none\" : theme.shadows.primaryButton,\n color: ctaDisabled ? theme.colors.muted : primaryButtonForeground,\n cursor: ctaDisabled ? \"default\" : \"pointer\",\n display: \"flex\",\n fontFamily: theme.fonts.sans,\n fontSize: \"14px\",\n fontWeight: 500,\n gap: \"8px\",\n height: \"44px\",\n justifyContent: \"center\",\n lineHeight: \"18px\",\n width: \"100%\",\n }}\n type=\"button\"\n >\n {sessionLoading ||\n ctaRateLoading ||\n walletActionPending ||\n (!hasConnectedWallet && walletChecking) ? (\n \n ) : selectedQuote && hasConnectedWallet ? (\n \n ) : null}\n {walletActionPending\n ? \"Connecting wallet...\"\n : !hasConnectedWallet && walletChecking\n ? \"Checking wallet...\"\n : sessionLoading\n ? \"Opening provider...\"\n : ctaRateLoading\n ? \"Fetching best rates...\"\n : destinationTokenUnsupportedMessage\n ? \"Token not supported\"\n : selectedQuote\n ? hasConnectedWallet\n ? `Pay ${formatCurrencyAmount(sourceAmount, sourceCurrencyCode)}`\n : \"Connect Wallet\"\n : \"Enter amount\"}\n \n\n {activeSheet === \"fees\" && (\n setActiveSheet(null)}\n title={`Buying ${formatPlainNumberDisplay(receiveAmount, 6)} ${toToken?.symbol ?? \"\"}`}\n >\n \n 1 {toToken?.symbol ?? \"token\"} ≈{\" \"}\n {selectedQuote &&\n parseDecimal(selectedQuote.destinationAmount)?.gt(0)\n ? formatCurrencyAmount(\n parseDecimal(selectedQuote.sourceAmount)?.div(\n parseDecimal(selectedQuote.destinationAmount) ??\n new Decimal(1),\n ),\n sourceCurrencyCode,\n )\n : \"--\"}\n \n
\n \n \n {receiveAmount\n ? `Cost of ${formatPlainNumberDisplay(receiveAmount, 6)} ${toToken?.symbol ?? \"\"}`.trim()\n : `Cost of ${toToken?.symbol ?? \"tokens\"}`}\n \n \n {tokenCostFiatValue\n ? formatCurrencyAmount(tokenCostFiatValue, sourceCurrencyCode)\n : \"--\"}\n \n
\n {[\n [\n selectedQuote?.provider\n ? `${getProviderLabel(selectedQuote.provider)} fee`\n : \"Provider fee\",\n selectedQuote?.fees?.provider,\n ],\n [\"Network fee\", selectedQuote?.fees?.network],\n [\"Partner fee\", selectedQuote?.fees?.partner],\n ].map(([label, value]) => (\n \n \n {label}\n \n \n {value\n ? formatCurrencyAmount(value, sourceCurrencyCode)\n : \"--\"}\n \n \n ))}\n \n \n Total you pay\n \n \n {formatCurrencyAmount(sourceAmount, sourceCurrencyCode)}\n \n \n \n \n )}\n\n {activeSheet === \"partner\" && (\n setActiveSheet(null)} title=\"Payment partner\">\n \n {filteredProviderOptions.length > 0 ? (\n \n {filteredProviderOptions.map((option) => {\n const optionIndex = providerOptions.findIndex(\n (candidate) =>\n candidate.provider === option.provider &&\n candidate.paymentMethodType === option.paymentMethodType,\n );\n const methodSubtitle = getMethodSubtitle(option.paymentMethod);\n const optionSubtitle = option.paymentMethodType\n ? [\n option.paymentMethod?.name ??\n getMethodLabel(option.paymentMethodType),\n methodSubtitle,\n ]\n .filter(Boolean)\n .join(\" · \")\n : \"Available route\";\n return (\n }\n key={`${option.provider}-${option.paymentMethodType ?? \"route\"}`}\n onClick={() => handleProviderSelect(option)}\n primary={optionIndex === 0}\n selected={option.provider === displayProvider}\n subtitle={optionSubtitle}\n title={getProviderLabel(option.provider)}\n value={\n option.destinationAmount\n ? `${formatPlainNumberDisplay(option.destinationAmount, 6)} ${toToken?.symbol ?? \"\"}`\n : undefined\n }\n />\n );\n })}\n \n ) : (\n No payment partners found.\n )}\n \n )}\n\n {activeSheet === \"country\" && (\n setActiveSheet(null)} title=\"Select country\">\n \n
Supported countries
\n {filteredCountries.length > 0 ? (\n \n {filteredCountries.map((country) => (\n \n }\n key={country.countryCode}\n onClick={() => {\n void handleCountrySelect(country.countryCode);\n setCountrySearch(\"\");\n }}\n selected={\n country.countryCode.toUpperCase() ===\n countryCode.toUpperCase()\n }\n subtitle={country.countryCode}\n title={country.name}\n />\n ))}\n \n ) : (\n No countries found.\n )}\n
\n )}\n\n {activeSheet === \"currency\" && (\n setActiveSheet(null)} title=\"Select currency\">\n \n
Fiat currencies
\n {filteredFiatCurrencies.length > 0 ? (\n \n {filteredFiatCurrencies.map((currency) => (\n }\n key={currency.currencyCode}\n onClick={() => {\n handleCurrencySelect(currency.currencyCode);\n setCurrencySearch(\"\");\n }}\n selected={currency.currencyCode === sourceCurrencyCode}\n subtitle={getFiatCurrencyName(\n currency.currencyCode,\n currency,\n )}\n title={currency.currencyCode}\n />\n ))}\n \n ) : (\n No currencies found.\n )}\n
\n )}\n\n {activeSheet === \"method\" && (\n setActiveSheet(null)} title=\"Payment method\">\n \n {filteredPaymentMethods.length > 0 ? (\n \n {filteredPaymentMethods.map((method) => (\n \n }\n key={method.method}\n onClick={() => handleMethodSelect(method.method)}\n selected={method.method === selectedPaymentMethod}\n subtitle={getMethodSubtitle(method)}\n title={method.name ?? getMethodLabel(method.method)}\n />\n ))}\n \n ) : (\n No payment methods found.\n )}\n \n )}\n\n {activeSheet === \"destination\" && (\n setActiveSheet(null)} title=\"Select token\">\n {availableDestinationTokens.length > 0 ? (\n \n {availableDestinationTokens.map((token) => (\n }\n key={getOnrampTokenKey(token)}\n onClick={() => handleDestinationTokenSelect(token)}\n selected={isSameOnrampToken(token, toToken)}\n subtitle={token.chainName}\n title={token.symbol}\n value={token.balanceInFiat}\n />\n ))}\n \n ) : (\n No tokens found.\n )}\n \n )}\n \n );\n}\n", + "type": "registry:component", + "target": "components/nexus/components/deposit-onramp-flow.tsx" + }, { "path": "registry/avail-widgets/nexus-widget/components/nexus-widget-progress-screen.tsx", - "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\n\"use client\";\n\nimport Decimal from \"decimal.js\";\nimport { Check, ChevronDown, Loader2, X } from \"lucide-react\";\nimport React, { useEffect, useState } from \"react\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport type {\n BridgeStepType,\n SwapStepType,\n} from \"../../common/types/transaction-flow\";\nimport { getShortChainName } from \"../../common/utils/constant\";\nimport {\n type NexusWidgetDepositOpportunityMetadata,\n type NexusWidgetMode,\n} from \"../types\";\nimport { type SwapTokenOption } from \"./swap-asset-selector\";\nimport { type SwapIntentData } from \"./swap-intent-preview\";\n\ntype ProgressSdkStep = SwapStepType | BridgeStepType;\n\ntype ProgressStep = {\n id: number;\n completed: boolean;\n step: ProgressSdkStep;\n};\n\nexport type NexusWidgetProgressEvent = {\n id: string;\n name: string;\n completed: boolean;\n event?: unknown;\n step?: ProgressSdkStep;\n steps?: ProgressSdkStep[];\n};\n\ninterface NexusWidgetProgressScreenProps {\n failedStep?: ProgressSdkStep | null;\n fromAmountUsd?: string;\n fromTokens?: SwapTokenOption[];\n intentData?: SwapIntentData | null;\n mode: NexusWidgetMode;\n opportunity?: NexusWidgetDepositOpportunityMetadata;\n progressEvents?: NexusWidgetProgressEvent[];\n recipientAddress?: string;\n steps?: ProgressStep[];\n toAmount?: string;\n toAmountUsd?: string;\n toToken?: SwapTokenOption;\n totalFeeUsd?: string;\n}\n\nconst fontFamily = '\"Geist\", var(--font-geist-sans), system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\nconst danger = \"var(--nexus-widget-error-text, #E92C2C)\";\n\nconst formatDecimal = (value: unknown, decimals = 2) =>\n (parseDecimal(value) ?? new Decimal(0)).toDecimalPlaces(decimals).toFixed();\n\nconst formatUsd = (value: unknown) => `$${formatDecimal(value, 2)}`;\n\nconst unique = (values: Array) =>\n Array.from(new Set(values.filter(Boolean) as string[]));\n\nconst formatSymbolSummary = (symbols: string[]) => {\n if (symbols.length <= 2) return symbols.join(\", \");\n return `${symbols.slice(0, 2).join(\", \")} and ${symbols.length - 2} others`;\n};\n\nconst getStepType = (step?: ProgressSdkStep) =>\n String((step as any)?.type ?? (step as any)?.typeID ?? \"\").toUpperCase();\n\ntype ProgressStatusId =\n | \"approveTokens\"\n | \"swapTokens\"\n | \"receiveToken\"\n | \"action\";\n\ntype ProgressStatusState =\n | \"default\"\n | \"preapproval\"\n | \"inProgress\"\n | \"completed\"\n | \"error\";\n\ntype ProgressStatusRow = {\n id: ProgressStatusId;\n label: string;\n description?: string;\n state: ProgressStatusState;\n};\n\nconst PROGRESS_EVENT_NAMES = {\n BRIDGE_PLAN_LIST: \"bridge_plan_list\",\n BRIDGE_PLAN_PROGRESS: \"bridge_plan_progress\",\n SWAP_PLAN_LIST: \"swap_plan_list\",\n SWAP_PLAN_PROGRESS: \"swap_plan_progress\",\n} as const;\n\ntype ProgressListEventName =\n | typeof PROGRESS_EVENT_NAMES.BRIDGE_PLAN_LIST\n | typeof PROGRESS_EVENT_NAMES.SWAP_PLAN_LIST;\n\nconst STATUS_ORDER: ProgressStatusId[] = [\n \"approveTokens\",\n \"swapTokens\",\n \"receiveToken\",\n \"action\",\n];\n\nconst SWAP_APPROVAL_TYPES = [\"ALLOWANCE\"];\n\nconst REFUND_ELIGIBLE_SWAP_TYPES = [\n \"BRIDGE_INTENT_SUBMISSION\",\n \"BRIDGE_DEPOSIT\",\n];\n\nconst DESTINATION_SWAP_TYPES = [\n \"DESTINATION_SWAP\",\n \"DESTINATION_SWAP_BATCH_TX\",\n \"DESTINATION_SWAP_HASH\",\n];\nconst BRIDGE_FILL_RECEIVE_TYPES = [\"BRIDGE_FILL\"];\n\nconst getStatusForStep = (\n step: ProgressSdkStep | undefined,\n mode: NexusWidgetMode,\n hasTransferAction = false,\n): ProgressStatusId | null => {\n const type = getStepType(step);\n\n if (\n type === \"APPROVAL\" ||\n type === \"TRANSACTION_SENT\" ||\n type === \"TRANSACTION_CONFIRMED\"\n ) {\n return mode === \"swap\" && !hasTransferAction ? null : \"action\";\n }\n\n if (type.includes(\"SWAP_START\")) {\n return \"swapTokens\";\n }\n\n if (SWAP_APPROVAL_TYPES.some((token) => type.includes(token))) {\n return \"approveTokens\";\n }\n\n if (\n type.includes(\"EOA_TO_EPHEMERAL_TRANSFER\") ||\n type.includes(\"SOURCE_SWAP\") ||\n type.includes(\"SOURCE_BATCH\") ||\n type.includes(\"SWAP_SOURCE\") ||\n type.includes(\"BRIDGE_DEPOSIT\") ||\n type.includes(\"BRIDGE_FILL\") ||\n type.includes(\"BRIDGE_INTENT_SUBMISSION\") ||\n type.includes(\"SWAP_COMPLETE\") ||\n type.includes(\"SWAP_SKIPPED\")\n ) {\n return \"swapTokens\";\n }\n\n if (type.includes(\"DESTINATION_SWAP\") || type.includes(\"DESTINATION_BATCH\")) {\n return \"receiveToken\";\n }\n\n return null;\n};\n\nconst stepMatches = (step: ProgressSdkStep | undefined, tokens: string[]) => {\n const type = getStepType(step);\n return tokens.some((token) => type.includes(token));\n};\n\nconst hasCompletedType = (\n events: NexusWidgetProgressEvent[],\n steps: ProgressStep[],\n tokens: string[],\n) => {\n const completedEvent = events.some(\n (event) => event.completed && stepMatches(event.step, tokens),\n );\n if (completedEvent) return true;\n\n return steps.some((item) => item.completed && stepMatches(item.step, tokens));\n};\n\nconst hasStepType = (\n events: NexusWidgetProgressEvent[],\n steps: ProgressStep[],\n tokens: string[],\n) =>\n events.some(\n (event) =>\n stepMatches(event.step, tokens) ||\n (event.steps ?? []).some((step) => stepMatches(step, tokens)),\n ) || steps.some((item) => stepMatches(item.step, tokens));\n\nconst hasEventType = (events: NexusWidgetProgressEvent[], tokens: string[]) =>\n events.some(\n (event) =>\n stepMatches(event.step, tokens) ||\n (event.steps ?? []).some((step) => stepMatches(step, tokens)),\n );\n\nconst hasProgressEventType = (\n events: NexusWidgetProgressEvent[],\n tokens: string[],\n) =>\n events.some(\n (event) =>\n (event.name === PROGRESS_EVENT_NAMES.BRIDGE_PLAN_PROGRESS ||\n event.name === PROGRESS_EVENT_NAMES.SWAP_PLAN_PROGRESS) &&\n stepMatches(event.step, tokens),\n );\n\nconst getListedSteps = (\n events: NexusWidgetProgressEvent[],\n eventName: ProgressListEventName,\n) => {\n const listEvent = [...events]\n .reverse()\n .find(\n (event) => event.name === eventName && event.steps !== undefined,\n );\n return listEvent?.steps ?? [];\n};\n\nconst countListedSteps = (steps: ProgressSdkStep[], tokens: string[]) =>\n steps.filter((step) => stepMatches(step, tokens)).length;\n\nconst getStepId = (step?: ProgressSdkStep) => step?.id ?? step?.typeID;\nconst getStepChainId = (step?: ProgressSdkStep) => step?.chain?.id ?? step?.chainId;\nconst isSameStep = (left?: ProgressSdkStep, right?: ProgressSdkStep) =>\n Boolean(left && right && getStepId(left) && getStepId(left) === getStepId(right));\nconst getEventState = (event: NexusWidgetProgressEvent) =>\n String((event.event as { state?: string } | undefined)?.state ?? \"\").toLowerCase();\n\n/** Allowances have no standalone swap progress events. The SDK reports them\n * through the associated swap/transfer/deposit on the same chain. */\nconst getApprovalProgress = (\n plan: ProgressSdkStep[],\n events: NexusWidgetProgressEvent[],\n steps: ProgressStep[],\n failedStep?: ProgressSdkStep | null,\n) => {\n const seen = new Set();\n const approvals = plan.flatMap((step, index) => {\n if (!stepMatches(step, SWAP_APPROVAL_TYPES)) return [];\n const key = String(getStepId(step));\n if (seen.has(key)) return [];\n seen.add(key);\n const tokenAddress = String(step.token?.contractAddress ?? \"\").toLowerCase();\n const owners = plan.slice(index + 1).filter((candidate) =>\n getStepChainId(candidate) === getStepChainId(step) &&\n [\"SOURCE_SWAP\", \"DESTINATION_SWAP\", \"EOA_TO_EPHEMERAL_TRANSFER\", \"BRIDGE_DEPOSIT\"]\n .includes(getStepType(candidate)),\n );\n const owner = getStepType(step) === \"ALLOWANCE_APPROVAL\" ? step :\n owners.find((candidate) => {\n const inputs = candidate.swaps?.map((swap: any) => swap.input) ?? [candidate.asset];\n return inputs.some((input: any) => tokenAddress &&\n String(input?.contractAddress ?? \"\").toLowerCase() === tokenAddress);\n }) ?? owners[0];\n const ownerEvents = events.filter((event) =>\n !event.steps && isSameStep(event.step, owner),\n );\n const completed = steps.some((item) => item.completed && isSameStep(item.step, owner)) ||\n ownerEvents.some((event) => event.completed ||\n [\"confirmed\", \"completed\"].includes(getEventState(event)) ||\n (getEventState(event) === \"submitted\" && getStepType(owner) !== \"ALLOWANCE_APPROVAL\") ||\n // Safe swap execution starts only after its permit/approval calls are prepared.\n (getEventState(event) === \"started\" &&\n [\"SOURCE_SWAP\", \"DESTINATION_SWAP\"].includes(getStepType(owner)))) ||\n (getStepType(owner) === \"EOA_TO_EPHEMERAL_TRANSFER\" && events.some((event) =>\n !event.steps && getStepType(event.step) === \"BRIDGE_DEPOSIT\" &&\n getStepChainId(event.step) === getStepChainId(owner) &&\n (event.completed || [\"submitted\", \"confirmed\"].includes(getEventState(event)))));\n const failed = !completed && (isSameStep(failedStep ?? undefined, step) ||\n isSameStep(failedStep ?? undefined, owner) ||\n ownerEvents.some((event) => getEventState(event) === \"failed\"));\n return [{ step, owner, completed, failed }];\n });\n const pending = approvals.filter((approval) => !approval.completed);\n const activeEvent = [...events].reverse().find((event) =>\n !event.steps && getEventState(event) === \"wallet_prompted\" &&\n pending.some((approval) => isSameStep(approval.owner, event.step)),\n );\n const activeOwner = activeEvent?.step ?? pending[0]?.owner;\n const active = pending.filter((approval) =>\n activeOwner ? isSameStep(approval.owner, activeOwner) : approval === pending[0],\n );\n const isCompleted = (step: ProgressSdkStep) =>\n steps.some((item) => item.completed && isSameStep(item.step, step)) ||\n events.some((event) => !event.steps && event.completed && isSameStep(event.step, step));\n const prerequisites = getStepType(activeOwner) === \"DESTINATION_SWAP\"\n ? plan.filter((step) => getStepType(step) === \"BRIDGE_FILL\")\n : [\"EOA_TO_EPHEMERAL_TRANSFER\", \"BRIDGE_DEPOSIT\"].includes(getStepType(activeOwner))\n ? plan.filter((step) => getStepType(step) === \"SOURCE_SWAP\")\n : [];\n return {\n total: approvals.length,\n completed: approvals.filter((approval) => approval.completed).length,\n failed: approvals.some((approval) => approval.failed),\n symbols: unique(active.map((approval) => approval.step.token?.symbol)),\n permitsOnly: active.length > 0 && active.every((approval) => approval.step.method === \"permit\"),\n pendingOwnerIds: new Set(pending.map((approval) => getStepId(approval.owner))),\n awaitingWallet: Boolean(activeEvent) || prerequisites.every(isCompleted),\n blocksSwapExecution: pending.some((approval) => getStepType(approval.owner) !== \"DESTINATION_SWAP\"),\n };\n};\n\nconst hasStartedStatus = (\n events: NexusWidgetProgressEvent[],\n id: ProgressStatusId,\n mode: NexusWidgetMode,\n hasTransferAction = false,\n) =>\n events.some(\n (event) => getStatusForStep(event.step, mode, hasTransferAction) === id,\n );\n\nexport const buildStatusRows = ({\n events,\n failedStep,\n mode,\n steps,\n context,\n}: {\n events: NexusWidgetProgressEvent[];\n failedStep?: ProgressSdkStep | null;\n mode: NexusWidgetMode;\n steps: ProgressStep[];\n context: {\n destinationChain?: string;\n destinationSymbol?: string;\n opportunityName?: string;\n recipientAddress?: string;\n };\n}): ProgressStatusRow[] => {\n const hasTransferAction =\n mode === \"send\" || (mode === \"swap\" && Boolean(context.recipientAddress));\n let failedStatus = failedStep\n ? getStatusForStep(failedStep, mode, hasTransferAction)\n : null;\n const swapListSteps = getListedSteps(\n events,\n PROGRESS_EVENT_NAMES.SWAP_PLAN_LIST,\n );\n const fallbackSteps = steps.map((item) => item.step);\n const currentPlan = events.some((event) =>\n event.name === PROGRESS_EVENT_NAMES.SWAP_PLAN_LIST && event.steps !== undefined,\n ) ? swapListSteps : fallbackSteps;\n const destinationSymbol = context.destinationSymbol || \"token\";\n const destinationChain = context.destinationChain || \"destination\";\n const opportunityName = context.opportunityName || \"app\";\n // The latest confirmed plan replaces provisional allowances; never freeze a preview count.\n const approval = getApprovalProgress(\n currentPlan,\n events,\n steps,\n failedStep,\n );\n const approvalTotal = approval.total;\n const approvalCompletedCount = approval.completed;\n if (approval.failed) failedStatus = \"approveTokens\";\n const refundEligibleFailure = Boolean(failedStep &&\n stepMatches(failedStep, REFUND_ELIGIBLE_SWAP_TYPES));\n const hasSwapList =\n swapListSteps.length > 0 ||\n hasStepType(events, steps, [\n \"SWAP_START\",\n \"DETERMINING_SWAP\",\n \"SOURCE_SWAP\",\n \"DESTINATION_SWAP\",\n \"BRIDGE_DEPOSIT\",\n \"BRIDGE_FILL\",\n \"BRIDGE_INTENT_SUBMISSION\",\n \"SWAP_COMPLETE\",\n \"SWAP_SKIPPED\",\n ]);\n const hasDestinationReceiveStep =\n countListedSteps(swapListSteps, DESTINATION_SWAP_TYPES) > 0 ||\n countListedSteps(fallbackSteps, DESTINATION_SWAP_TYPES) > 0 ||\n hasProgressEventType(events, DESTINATION_SWAP_TYPES);\n const receiveTokenTypes = hasDestinationReceiveStep\n ? DESTINATION_SWAP_TYPES\n : BRIDGE_FILL_RECEIVE_TYPES;\n const hasReceiveTokenStep =\n hasDestinationReceiveStep ||\n countListedSteps(swapListSteps, receiveTokenTypes) > 0 ||\n countListedSteps(fallbackSteps, receiveTokenTypes) > 0 ||\n hasProgressEventType(events, receiveTokenTypes);\n const receiveTokenStarted = events.some((event) =>\n !event.steps && stepMatches(event.step, receiveTokenTypes) &&\n !approval.pendingOwnerIds.has(getStepId(event.step)),\n );\n const receiveTokenComplete =\n hasReceiveTokenStep && hasCompletedType(events, steps, receiveTokenTypes);\n const swapComplete = hasCompletedType(events, steps, [\n \"SWAP_COMPLETE\",\n \"SWAP_SKIPPED\",\n ]);\n const swapSkipped = hasCompletedType(events, steps, [\"SWAP_SKIPPED\"]);\n const shouldShowSwapRows =\n hasSwapList && !(swapSkipped && (mode === \"deposit\" || mode === \"send\"));\n const swapExecutionSteps = currentPlan.filter((step) =>\n getStatusForStep(step, mode, hasTransferAction) === \"swapTokens\",\n );\n const swapExecutionComplete = swapExecutionSteps.length > 0 && swapExecutionSteps.every((step) =>\n steps.some((item) => item.completed && isSameStep(item.step, step)) ||\n events.some((event) => !event.steps && event.completed && isSameStep(event.step, step)),\n );\n const swapTokensComplete = hasReceiveTokenStep\n ? receiveTokenStarted\n : swapComplete || swapExecutionComplete;\n const transactionSent = hasCompletedType(events, steps, [\"TRANSACTION_SENT\"]) ||\n events.some((event) => !event.steps && getStepType(event.step) === \"TRANSACTION_SENT\" &&\n getEventState(event) === \"submitted\");\n const transactionConfirmed = hasCompletedType(events, steps, [\n \"TRANSACTION_CONFIRMED\",\n ]);\n const rows: ProgressStatusRow[] = [];\n\n const pushRow = (row: ProgressStatusRow) => {\n if (failedStatus) {\n const failedIndex = STATUS_ORDER.indexOf(failedStatus);\n const currentIndex = STATUS_ORDER.indexOf(row.id);\n if (failedIndex >= 0 && currentIndex > failedIndex) return;\n }\n rows.push(row);\n };\n\n if (approvalTotal > 0) {\n const approvalCurrent = Math.min(\n approvalTotal,\n Math.max(1, approvalCompletedCount + 1),\n );\n const symbols = formatSymbolSummary(approval.symbols);\n const approvalDescription = symbols\n ? `${approval.permitsOnly ? \"Sign permit for\" : \"Approve\"} ${symbols} in wallet`\n : \"Approve in wallet\";\n const state: ProgressStatusState = failedStatus === \"approveTokens\"\n ? \"error\"\n : approvalCompletedCount >= approvalTotal\n ? \"completed\"\n : approval.awaitingWallet ? \"preapproval\" : \"default\";\n\n pushRow({\n id: \"approveTokens\",\n state,\n description: state === \"preapproval\" ? approvalDescription : undefined,\n label:\n state === \"completed\"\n ? `Tokens approved for swap (${approvalTotal} of ${approvalTotal})`\n : state === \"error\"\n ? \"Token approval failed\"\n : `Approve tokens for swap (${approvalCurrent} of ${approvalTotal})`,\n });\n }\n\n if (shouldShowSwapRows) {\n const approvalsSatisfied = !approval.blocksSwapExecution;\n let state: ProgressStatusState = \"default\";\n if (failedStatus === \"swapTokens\") {\n state = \"error\";\n } else if (swapTokensComplete) {\n state = \"completed\";\n } else if (\n approvalsSatisfied &&\n (hasStartedStatus(events, \"swapTokens\", mode, hasTransferAction) ||\n hasEventType(events, [\n \"DESTINATION_SWAP_BATCH_TX\",\n \"BRIDGE_DEPOSIT\",\n \"SOURCE_SWAP_BATCH_TX\",\n \"SOURCE_SWAP_HASH\",\n \"SWAP_START\",\n ]))\n ) {\n state = \"inProgress\";\n }\n\n pushRow({\n id: \"swapTokens\",\n state,\n label:\n state === \"completed\"\n ? \"Swaps completed\"\n : state === \"error\"\n ? refundEligibleFailure\n ? \"Swap failed. Refund initiated\"\n : \"Swap failed\"\n : state === \"inProgress\"\n ? \"Swaps in progress\"\n : \"Swap tokens\",\n });\n\n if (hasReceiveTokenStep) {\n pushRow({\n id: \"receiveToken\",\n state:\n failedStatus === \"receiveToken\"\n ? \"error\"\n : receiveTokenComplete\n ? \"completed\"\n : receiveTokenStarted\n ? \"inProgress\"\n : \"default\",\n label:\n failedStatus === \"receiveToken\"\n ? refundEligibleFailure\n ? \"Destination swap failed. Refund initiated.\"\n : \"Destination swap failed.\"\n : receiveTokenComplete\n ? `Received ${destinationSymbol} on ${destinationChain}`\n : receiveTokenStarted\n ? `Receiving ${destinationSymbol} on ${destinationChain}`\n : `Receive ${destinationSymbol} on ${destinationChain}`,\n });\n }\n }\n\n if (mode === \"deposit\" || hasTransferAction) {\n const receiveComplete =\n swapSkipped ||\n !shouldShowSwapRows ||\n (hasReceiveTokenStep ? receiveTokenComplete : swapTokensComplete);\n const isDeposit = mode === \"deposit\";\n let state: ProgressStatusState = \"default\";\n if (failedStatus === \"action\") {\n state = \"error\";\n } else if (transactionConfirmed) {\n state = \"completed\";\n } else if (transactionSent) {\n state = \"inProgress\";\n } else if (receiveComplete) {\n state = \"preapproval\";\n }\n\n pushRow({\n id: \"action\",\n state,\n description: state === \"preapproval\" ? \"Approve in wallet\" : undefined,\n label: isDeposit\n ? state === \"completed\"\n ? `${destinationSymbol} deposited to ${opportunityName}`\n : state === \"inProgress\"\n ? `Depositing ${destinationSymbol} to ${opportunityName}`\n : state === \"error\"\n ? \"Deposit failed. Funds are in your wallet.\"\n : state === \"preapproval\"\n ? `Approve Deposit of ${destinationSymbol} to ${opportunityName}`\n : `Deposit ${destinationSymbol} to ${opportunityName}`\n : state === \"completed\"\n ? `${destinationSymbol} sent`\n : state === \"inProgress\"\n ? `Sending ${destinationSymbol}`\n : state === \"error\"\n ? \"Send failed. Funds are in your wallet.\"\n : state === \"preapproval\"\n ? `Approve ${destinationSymbol} transfer`\n : `Send ${destinationSymbol}`,\n });\n }\n\n const orderedRows = rows.sort(\n (a, b) => STATUS_ORDER.indexOf(a.id) - STATUS_ORDER.indexOf(b.id),\n );\n\n if (\n orderedRows.some(\n (row) => row.state === \"preapproval\" || row.state === \"inProgress\",\n ) ||\n orderedRows.some((row) => row.state === \"error\")\n ) {\n return orderedRows;\n }\n\n const nextActiveIndex = orderedRows.findIndex(\n (row) => row.state === \"default\",\n );\n if (nextActiveIndex === -1) return orderedRows;\n\n return orderedRows.map((row, index) => {\n if (index !== nextActiveIndex) return row;\n const nextState =\n row.id === \"approveTokens\" || row.id === \"action\"\n ? \"preapproval\"\n : \"inProgress\";\n return {\n ...row,\n description:\n nextState === \"preapproval\" ? \"Approve in wallet\" : undefined,\n label:\n row.id === \"swapTokens\"\n ? \"Swaps in progress\"\n : row.id === \"receiveToken\"\n ? `Receiving ${destinationSymbol} on ${destinationChain}`\n : row.label,\n state: nextState,\n };\n });\n};\n\nfunction MiniLogo({\n src,\n label,\n size,\n style,\n}: {\n src?: string;\n label?: string;\n size: number;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n background: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").trim().slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction TokenLogoPair({\n tokenLogo,\n chainLogo,\n tokenSymbol,\n chainName,\n}: {\n tokenLogo?: string;\n chainLogo?: string;\n tokenSymbol?: string;\n chainName?: string;\n}) {\n return (\n \n \n {chainLogo && (\n \n )}\n \n );\n}\n\nexport function NexusWidgetProgressScreen({\n fromTokens = [],\n toToken,\n fromAmountUsd,\n toAmount,\n toAmountUsd,\n totalFeeUsd,\n intentData,\n mode,\n opportunity,\n steps,\n progressEvents = [],\n failedStep,\n recipientAddress,\n}: NexusWidgetProgressScreenProps) {\n const intentSources = intentData?.sources ?? [];\n const intentDestination = intentData?.destination;\n const destinationSourceToken = fromTokens.find((token) => {\n const destinationChainId = intentDestination?.chain.id ?? toToken?.chainId;\n const destinationTokenAddress = (\n intentDestination?.token.contractAddress ??\n toToken?.contractAddress ??\n \"\"\n ).toLowerCase();\n const tokenAmount =\n parseDecimal(token.userAmount) ?? parseDecimal(token.balance);\n\n return (\n destinationChainId !== undefined &&\n destinationTokenAddress !== \"\" &&\n token.chainId === destinationChainId &&\n token.contractAddress.toLowerCase() === destinationTokenAddress &&\n Boolean(tokenAmount && tokenAmount.gt(0))\n );\n });\n const sourceSymbols = unique([\n ...(destinationSourceToken ? [destinationSourceToken.symbol] : []),\n ...(intentSources.length > 0\n ? intentSources.map((source) => source.token.symbol)\n : fromTokens.map((token) => token.symbol)),\n ]);\n const intentSourceUsd =\n intentSources.length > 0\n ? intentSources.reduce(\n (sum, source) => sum.plus(parseDecimal(source.value) ?? 0),\n new Decimal(0),\n )\n : parseDecimal(fromAmountUsd);\n const requestedDestinationAmount = parseDecimal(toAmount);\n const quotedDestinationAmount = parseDecimal(intentDestination?.amount);\n const destinationBalanceAmount = parseDecimal(toToken?.balance);\n const requestedDestinationUsd = parseDecimal(toAmountUsd);\n const destinationUsdRate =\n requestedDestinationAmount &&\n requestedDestinationAmount.gt(0) &&\n requestedDestinationUsd &&\n requestedDestinationUsd.gt(0)\n ? requestedDestinationUsd.div(requestedDestinationAmount)\n : quotedDestinationAmount &&\n quotedDestinationAmount.gt(0) &&\n intentDestination?.value\n ? (parseDecimal(intentDestination.value) ?? new Decimal(0)).div(\n quotedDestinationAmount,\n )\n : undefined;\n const destinationCoverageUsd =\n (mode === \"deposit\" || mode === \"send\") &&\n requestedDestinationAmount &&\n requestedDestinationAmount.gt(0) &&\n quotedDestinationAmount &&\n requestedDestinationAmount.gt(quotedDestinationAmount) &&\n destinationBalanceAmount &&\n destinationBalanceAmount.gt(0) &&\n destinationUsdRate &&\n destinationUsdRate.gt(0)\n ? Decimal.min(\n requestedDestinationAmount.minus(quotedDestinationAmount),\n destinationBalanceAmount,\n ).mul(destinationUsdRate)\n : undefined;\n const quotedDestinationUsd = parseDecimal(intentDestination?.value);\n const feeUsd = parseDecimal(totalFeeUsd);\n const sourceUsd =\n mode === \"deposit\" || mode === \"send\"\n ? [\n destinationCoverageUsd !== undefined\n ? (intentSourceUsd ?? new Decimal(0)).plus(destinationCoverageUsd)\n : intentSourceUsd,\n requestedDestinationUsd,\n requestedDestinationUsd &&\n requestedDestinationUsd.gt(0) &&\n intentSourceUsd &&\n intentSourceUsd.gt(0) &&\n quotedDestinationUsd &&\n quotedDestinationUsd.gt(0)\n ? requestedDestinationUsd.plus(\n Decimal.max(intentSourceUsd.minus(quotedDestinationUsd), 0),\n )\n : undefined,\n requestedDestinationUsd &&\n requestedDestinationUsd.gt(0) &&\n feeUsd &&\n feeUsd.gt(0)\n ? requestedDestinationUsd.plus(feeUsd)\n : undefined,\n ]\n .filter((value): value is Decimal => Boolean(value && value.gt(0)))\n .reduce(\n (max, value) => (!max || value.gt(max) ? value : max),\n undefined,\n )\n : intentSourceUsd;\n const destinationAmount =\n (mode === \"deposit\" || mode === \"send\") && toAmount\n ? toAmount\n : (intentDestination?.amount ?? toAmount ?? \"0\");\n const destinationSymbol =\n intentDestination?.token.symbol ||\n toToken?.symbol ||\n opportunity?.tokenSymbol ||\n \"\";\n const destinationChainName = getShortChainName(\n intentDestination?.chain.id ?? toToken?.chainId,\n intentDestination?.chain.name || toToken?.chainName || \"\",\n );\n const destinationChain =\n mode === \"deposit\"\n ? opportunity?.title || opportunity?.protocol || destinationChainName\n : destinationChainName;\n const statusRows = buildStatusRows({\n events: progressEvents,\n failedStep,\n mode,\n steps: steps ?? [],\n context: {\n destinationChain: destinationChainName || destinationChain,\n destinationSymbol,\n opportunityName: opportunity?.title || opportunity?.protocol,\n recipientAddress,\n },\n });\n const [stepsExpanded, setStepsExpanded] = useState(true);\n const activeRow =\n statusRows.find(\n (row) => row.state === \"preapproval\" || row.state === \"inProgress\",\n ) ??\n statusRows.find((row) => row.state === \"error\") ??\n statusRows.find((row) => row.state === \"default\") ??\n statusRows[statusRows.length - 1];\n const visibleRows = stepsExpanded ? statusRows : activeRow ? [activeRow] : [];\n const canExpand = statusRows.length > 1;\n const getRowHeight = (row: ProgressStatusRow) => (row.description ? 47 : 40);\n const collapsedStatusHeight = activeRow ? getRowHeight(activeRow) : 40;\n const expandedStatusHeight = statusRows.reduce(\n (sum, row) => sum + getRowHeight(row),\n 0,\n );\n\n return (\n \n \n \n {formatSymbolSummary(sourceSymbols)}\n \n \n {formatUsd(sourceUsd)}\n \n\n \n\n \n \n \n {formatDecimal(destinationAmount, 8)}\n \n {destinationSymbol}\n \n \n {destinationChain && (\n \n on {destinationChain}\n \n )}\n \n \n\n \n \n \n {visibleRows.map((row, index) => {\n const isCompleted = row.state === \"completed\";\n const isError = row.state === \"error\";\n const isDefault = row.state === \"default\";\n const isLoading =\n row.state === \"preapproval\" || row.state === \"inProgress\";\n const hasDescription = Boolean(row.description);\n const rowColor = isDefault ? muted : isError ? danger : primary;\n\n return (\n {\n if (canExpand) setStepsExpanded((current) => !current);\n }}\n style={{\n alignItems: hasDescription ? \"flex-start\" : \"center\",\n appearance: \"none\",\n background: \"transparent\",\n border: \"0\",\n borderTop:\n index > 0 && stepsExpanded ? `1px solid ${border}` : \"0\",\n boxSizing: \"border-box\",\n color: rowColor,\n cursor: canExpand ? \"pointer\" : \"default\",\n display: \"flex\",\n fontFamily,\n fontSize: \"11px\",\n fontWeight: 400,\n gap: \"7px\",\n minHeight: `${getRowHeight(row)}px`,\n padding: \"8px 11px\",\n textAlign: \"left\",\n transition:\n \"color 220ms ease, min-height 220ms ease, opacity 220ms ease\",\n width: \"100%\",\n }}\n type=\"button\"\n >\n {isCompleted || isError ? (\n \n {isError ? (\n \n ) : (\n \n )}\n \n ) : isDefault ? (\n \n ) : (\n \n )}\n \n \n {row.label}\n \n {row.description && (\n \n {row.description}\n \n )}\n \n {canExpand && index === 0 && (\n \n )}\n \n );\n })}\n \n \n \n \n );\n}\n", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\n\"use client\";\n\nimport Decimal from \"decimal.js\";\nimport { Check, ChevronDown, Loader2, X } from \"lucide-react\";\nimport React, { useEffect, useState } from \"react\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport type {\n BridgeStepType,\n SwapStepType,\n} from \"../../common/types/transaction-flow\";\nimport { getShortChainName } from \"../../common/utils/constant\";\nimport {\n type NexusWidgetDepositOpportunityMetadata,\n type NexusWidgetMode,\n} from \"../types\";\nimport { NEXUS_WIDGET_FAST_SPINNER_STYLE } from \"../theme\";\nimport { type SwapTokenOption } from \"./swap-asset-selector\";\nimport { type SwapIntentData } from \"./swap-intent-preview\";\n\ntype ProgressSdkStep = SwapStepType | BridgeStepType;\n\ntype ProgressStep = {\n id: number;\n completed: boolean;\n step: ProgressSdkStep;\n};\n\nexport type NexusWidgetProgressEvent = {\n id: string;\n name: string;\n completed: boolean;\n event?: unknown;\n step?: ProgressSdkStep;\n steps?: ProgressSdkStep[];\n};\n\ninterface NexusWidgetProgressScreenProps {\n failedStep?: ProgressSdkStep | null;\n fromAmountUsd?: string;\n fromTokens?: SwapTokenOption[];\n intentData?: SwapIntentData | null;\n mode: NexusWidgetMode;\n opportunity?: NexusWidgetDepositOpportunityMetadata;\n progressEvents?: NexusWidgetProgressEvent[];\n recipientAddress?: string;\n steps?: ProgressStep[];\n toAmount?: string;\n toAmountUsd?: string;\n toToken?: SwapTokenOption;\n totalFeeUsd?: string;\n}\n\nconst fontFamily = '\"Geist\", var(--font-geist-sans), system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\nconst danger = \"var(--nexus-widget-error-text, #E92C2C)\";\n\nconst formatDecimal = (value: unknown, decimals = 2) =>\n (parseDecimal(value) ?? new Decimal(0)).toDecimalPlaces(decimals).toFixed();\n\nconst formatUsd = (value: unknown) => `$${formatDecimal(value, 2)}`;\n\nconst unique = (values: Array) =>\n Array.from(new Set(values.filter(Boolean) as string[]));\n\nconst formatSymbolSummary = (symbols: string[]) => {\n if (symbols.length <= 2) return symbols.join(\", \");\n return `${symbols.slice(0, 2).join(\", \")} and ${symbols.length - 2} others`;\n};\n\nconst getStepType = (step?: ProgressSdkStep) =>\n String((step as any)?.type ?? (step as any)?.typeID ?? \"\").toUpperCase();\n\ntype ProgressStatusId =\n | \"approveTokens\"\n | \"swapTokens\"\n | \"receiveToken\"\n | \"action\";\n\ntype ProgressStatusState =\n | \"default\"\n | \"preapproval\"\n | \"inProgress\"\n | \"completed\"\n | \"error\";\n\ntype ProgressStatusRow = {\n id: ProgressStatusId;\n label: string;\n description?: string;\n state: ProgressStatusState;\n};\n\nconst PROGRESS_EVENT_NAMES = {\n BRIDGE_PLAN_LIST: \"bridge_plan_list\",\n BRIDGE_PLAN_PROGRESS: \"bridge_plan_progress\",\n SWAP_PLAN_LIST: \"swap_plan_list\",\n SWAP_PLAN_PROGRESS: \"swap_plan_progress\",\n} as const;\n\ntype ProgressListEventName =\n | typeof PROGRESS_EVENT_NAMES.BRIDGE_PLAN_LIST\n | typeof PROGRESS_EVENT_NAMES.SWAP_PLAN_LIST;\n\nconst STATUS_ORDER: ProgressStatusId[] = [\n \"approveTokens\",\n \"swapTokens\",\n \"receiveToken\",\n \"action\",\n];\n\nconst SWAP_APPROVAL_TYPES = [\"ALLOWANCE\"];\n\nconst REFUND_ELIGIBLE_SWAP_TYPES = [\n \"BRIDGE_INTENT_SUBMISSION\",\n \"BRIDGE_DEPOSIT\",\n];\n\nconst DESTINATION_SWAP_TYPES = [\n \"DESTINATION_SWAP\",\n \"DESTINATION_SWAP_BATCH_TX\",\n \"DESTINATION_SWAP_HASH\",\n];\nconst BRIDGE_FILL_RECEIVE_TYPES = [\"BRIDGE_FILL\"];\n\nconst getStatusForStep = (\n step: ProgressSdkStep | undefined,\n mode: NexusWidgetMode,\n hasTransferAction = false,\n): ProgressStatusId | null => {\n const type = getStepType(step);\n\n if (\n type === \"APPROVAL\" ||\n type === \"TRANSACTION_SENT\" ||\n type === \"TRANSACTION_CONFIRMED\"\n ) {\n return mode === \"swap\" && !hasTransferAction ? null : \"action\";\n }\n\n if (type.includes(\"SWAP_START\")) {\n return \"swapTokens\";\n }\n\n if (SWAP_APPROVAL_TYPES.some((token) => type.includes(token))) {\n return \"approveTokens\";\n }\n\n if (\n type.includes(\"EOA_TO_EPHEMERAL_TRANSFER\") ||\n type.includes(\"SOURCE_SWAP\") ||\n type.includes(\"SOURCE_BATCH\") ||\n type.includes(\"SWAP_SOURCE\") ||\n type.includes(\"BRIDGE_DEPOSIT\") ||\n type.includes(\"BRIDGE_FILL\") ||\n type.includes(\"BRIDGE_INTENT_SUBMISSION\") ||\n type.includes(\"SWAP_COMPLETE\") ||\n type.includes(\"SWAP_SKIPPED\")\n ) {\n return \"swapTokens\";\n }\n\n if (type.includes(\"DESTINATION_SWAP\") || type.includes(\"DESTINATION_BATCH\")) {\n return \"receiveToken\";\n }\n\n return null;\n};\n\nconst stepMatches = (step: ProgressSdkStep | undefined, tokens: string[]) => {\n const type = getStepType(step);\n return tokens.some((token) => type.includes(token));\n};\n\nconst hasCompletedType = (\n events: NexusWidgetProgressEvent[],\n steps: ProgressStep[],\n tokens: string[],\n) => {\n const completedEvent = events.some(\n (event) => event.completed && stepMatches(event.step, tokens),\n );\n if (completedEvent) return true;\n\n return steps.some((item) => item.completed && stepMatches(item.step, tokens));\n};\n\nconst hasStepType = (\n events: NexusWidgetProgressEvent[],\n steps: ProgressStep[],\n tokens: string[],\n) =>\n events.some(\n (event) =>\n stepMatches(event.step, tokens) ||\n (event.steps ?? []).some((step) => stepMatches(step, tokens)),\n ) || steps.some((item) => stepMatches(item.step, tokens));\n\nconst hasEventType = (events: NexusWidgetProgressEvent[], tokens: string[]) =>\n events.some(\n (event) =>\n stepMatches(event.step, tokens) ||\n (event.steps ?? []).some((step) => stepMatches(step, tokens)),\n );\n\nconst hasProgressEventType = (\n events: NexusWidgetProgressEvent[],\n tokens: string[],\n) =>\n events.some(\n (event) =>\n (event.name === PROGRESS_EVENT_NAMES.BRIDGE_PLAN_PROGRESS ||\n event.name === PROGRESS_EVENT_NAMES.SWAP_PLAN_PROGRESS) &&\n stepMatches(event.step, tokens),\n );\n\nconst getListedSteps = (\n events: NexusWidgetProgressEvent[],\n eventName: ProgressListEventName,\n) => {\n const listEvent = [...events]\n .reverse()\n .find(\n (event) => event.name === eventName && event.steps !== undefined,\n );\n return listEvent?.steps ?? [];\n};\n\nconst countListedSteps = (steps: ProgressSdkStep[], tokens: string[]) =>\n steps.filter((step) => stepMatches(step, tokens)).length;\n\nconst getStepId = (step?: ProgressSdkStep) => step?.id ?? step?.typeID;\nconst getStepChainId = (step?: ProgressSdkStep) => step?.chain?.id ?? step?.chainId;\nconst isSameStep = (left?: ProgressSdkStep, right?: ProgressSdkStep) =>\n Boolean(left && right && getStepId(left) && getStepId(left) === getStepId(right));\nconst getEventState = (event: NexusWidgetProgressEvent) =>\n String((event.event as { state?: string } | undefined)?.state ?? \"\").toLowerCase();\n\n/** Allowances have no standalone swap progress events. The SDK reports them\n * through the associated swap/transfer/deposit on the same chain. */\nconst getApprovalProgress = (\n plan: ProgressSdkStep[],\n events: NexusWidgetProgressEvent[],\n steps: ProgressStep[],\n failedStep?: ProgressSdkStep | null,\n) => {\n const seen = new Set();\n const approvals = plan.flatMap((step, index) => {\n if (!stepMatches(step, SWAP_APPROVAL_TYPES)) return [];\n const key = String(getStepId(step));\n if (seen.has(key)) return [];\n seen.add(key);\n const tokenAddress = String(step.token?.contractAddress ?? \"\").toLowerCase();\n const owners = plan.slice(index + 1).filter((candidate) =>\n getStepChainId(candidate) === getStepChainId(step) &&\n [\"SOURCE_SWAP\", \"DESTINATION_SWAP\", \"EOA_TO_EPHEMERAL_TRANSFER\", \"BRIDGE_DEPOSIT\"]\n .includes(getStepType(candidate)),\n );\n const owner = getStepType(step) === \"ALLOWANCE_APPROVAL\" ? step :\n owners.find((candidate) => {\n const inputs = candidate.swaps?.map((swap: any) => swap.input) ?? [candidate.asset];\n return inputs.some((input: any) => tokenAddress &&\n String(input?.contractAddress ?? \"\").toLowerCase() === tokenAddress);\n }) ?? owners[0];\n const ownerEvents = events.filter((event) =>\n !event.steps && isSameStep(event.step, owner),\n );\n const completed = steps.some((item) => item.completed && isSameStep(item.step, owner)) ||\n ownerEvents.some((event) => event.completed ||\n [\"confirmed\", \"completed\"].includes(getEventState(event)) ||\n (getEventState(event) === \"submitted\" && getStepType(owner) !== \"ALLOWANCE_APPROVAL\") ||\n // Safe swap execution starts only after its permit/approval calls are prepared.\n (getEventState(event) === \"started\" &&\n [\"SOURCE_SWAP\", \"DESTINATION_SWAP\"].includes(getStepType(owner)))) ||\n (getStepType(owner) === \"EOA_TO_EPHEMERAL_TRANSFER\" && events.some((event) =>\n !event.steps && getStepType(event.step) === \"BRIDGE_DEPOSIT\" &&\n getStepChainId(event.step) === getStepChainId(owner) &&\n (event.completed || [\"submitted\", \"confirmed\"].includes(getEventState(event)))));\n const failed = !completed && (isSameStep(failedStep ?? undefined, step) ||\n isSameStep(failedStep ?? undefined, owner) ||\n ownerEvents.some((event) => getEventState(event) === \"failed\"));\n return [{ step, owner, completed, failed }];\n });\n const pending = approvals.filter((approval) => !approval.completed);\n const activeEvent = [...events].reverse().find((event) =>\n !event.steps && getEventState(event) === \"wallet_prompted\" &&\n pending.some((approval) => isSameStep(approval.owner, event.step)),\n );\n const activeOwner = activeEvent?.step ?? pending[0]?.owner;\n const active = pending.filter((approval) =>\n activeOwner ? isSameStep(approval.owner, activeOwner) : approval === pending[0],\n );\n const isCompleted = (step: ProgressSdkStep) =>\n steps.some((item) => item.completed && isSameStep(item.step, step)) ||\n events.some((event) => !event.steps && event.completed && isSameStep(event.step, step));\n const prerequisites = getStepType(activeOwner) === \"DESTINATION_SWAP\"\n ? plan.filter((step) => getStepType(step) === \"BRIDGE_FILL\")\n : [\"EOA_TO_EPHEMERAL_TRANSFER\", \"BRIDGE_DEPOSIT\"].includes(getStepType(activeOwner))\n ? plan.filter((step) => getStepType(step) === \"SOURCE_SWAP\")\n : [];\n return {\n total: approvals.length,\n completed: approvals.filter((approval) => approval.completed).length,\n failed: approvals.some((approval) => approval.failed),\n symbols: unique(active.map((approval) => approval.step.token?.symbol)),\n permitsOnly: active.length > 0 && active.every((approval) => approval.step.method === \"permit\"),\n pendingOwnerIds: new Set(pending.map((approval) => getStepId(approval.owner))),\n awaitingWallet: Boolean(activeEvent) || prerequisites.every(isCompleted),\n blocksSwapExecution: pending.some((approval) => getStepType(approval.owner) !== \"DESTINATION_SWAP\"),\n };\n};\n\nconst hasStartedStatus = (\n events: NexusWidgetProgressEvent[],\n id: ProgressStatusId,\n mode: NexusWidgetMode,\n hasTransferAction = false,\n) =>\n events.some(\n (event) => getStatusForStep(event.step, mode, hasTransferAction) === id,\n );\n\nexport const buildStatusRows = ({\n events,\n failedStep,\n mode,\n steps,\n context,\n}: {\n events: NexusWidgetProgressEvent[];\n failedStep?: ProgressSdkStep | null;\n mode: NexusWidgetMode;\n steps: ProgressStep[];\n context: {\n destinationChain?: string;\n destinationSymbol?: string;\n opportunityName?: string;\n recipientAddress?: string;\n };\n}): ProgressStatusRow[] => {\n const hasTransferAction =\n mode === \"send\" || (mode === \"swap\" && Boolean(context.recipientAddress));\n let failedStatus = failedStep\n ? getStatusForStep(failedStep, mode, hasTransferAction)\n : null;\n const swapListSteps = getListedSteps(\n events,\n PROGRESS_EVENT_NAMES.SWAP_PLAN_LIST,\n );\n const fallbackSteps = steps.map((item) => item.step);\n const currentPlan = events.some((event) =>\n event.name === PROGRESS_EVENT_NAMES.SWAP_PLAN_LIST && event.steps !== undefined,\n ) ? swapListSteps : fallbackSteps;\n const destinationSymbol = context.destinationSymbol || \"token\";\n const destinationChain = context.destinationChain || \"destination\";\n const opportunityName = context.opportunityName || \"app\";\n // The latest confirmed plan replaces provisional allowances; never freeze a preview count.\n const approval = getApprovalProgress(\n currentPlan,\n events,\n steps,\n failedStep,\n );\n const approvalTotal = approval.total;\n const approvalCompletedCount = approval.completed;\n if (approval.failed) failedStatus = \"approveTokens\";\n const refundEligibleFailure = Boolean(failedStep &&\n stepMatches(failedStep, REFUND_ELIGIBLE_SWAP_TYPES));\n const hasSwapList =\n swapListSteps.length > 0 ||\n hasStepType(events, steps, [\n \"SWAP_START\",\n \"DETERMINING_SWAP\",\n \"SOURCE_SWAP\",\n \"DESTINATION_SWAP\",\n \"BRIDGE_DEPOSIT\",\n \"BRIDGE_FILL\",\n \"BRIDGE_INTENT_SUBMISSION\",\n \"SWAP_COMPLETE\",\n \"SWAP_SKIPPED\",\n ]);\n const hasDestinationReceiveStep =\n countListedSteps(swapListSteps, DESTINATION_SWAP_TYPES) > 0 ||\n countListedSteps(fallbackSteps, DESTINATION_SWAP_TYPES) > 0 ||\n hasProgressEventType(events, DESTINATION_SWAP_TYPES);\n const receiveTokenTypes = hasDestinationReceiveStep\n ? DESTINATION_SWAP_TYPES\n : BRIDGE_FILL_RECEIVE_TYPES;\n const hasReceiveTokenStep =\n hasDestinationReceiveStep ||\n countListedSteps(swapListSteps, receiveTokenTypes) > 0 ||\n countListedSteps(fallbackSteps, receiveTokenTypes) > 0 ||\n hasProgressEventType(events, receiveTokenTypes);\n const receiveTokenStarted = events.some((event) =>\n !event.steps && stepMatches(event.step, receiveTokenTypes) &&\n !approval.pendingOwnerIds.has(getStepId(event.step)),\n );\n const receiveTokenComplete =\n hasReceiveTokenStep && hasCompletedType(events, steps, receiveTokenTypes);\n const swapComplete = hasCompletedType(events, steps, [\n \"SWAP_COMPLETE\",\n \"SWAP_SKIPPED\",\n ]);\n const swapSkipped = hasCompletedType(events, steps, [\"SWAP_SKIPPED\"]);\n const shouldShowSwapRows =\n hasSwapList && !(swapSkipped && (mode === \"deposit\" || mode === \"send\"));\n const swapExecutionSteps = currentPlan.filter((step) =>\n getStatusForStep(step, mode, hasTransferAction) === \"swapTokens\",\n );\n const swapExecutionComplete = swapExecutionSteps.length > 0 && swapExecutionSteps.every((step) =>\n steps.some((item) => item.completed && isSameStep(item.step, step)) ||\n events.some((event) => !event.steps && event.completed && isSameStep(event.step, step)),\n );\n const swapTokensComplete = hasReceiveTokenStep\n ? receiveTokenStarted\n : swapComplete || swapExecutionComplete;\n const transactionSent = hasCompletedType(events, steps, [\"TRANSACTION_SENT\"]) ||\n events.some((event) => !event.steps && getStepType(event.step) === \"TRANSACTION_SENT\" &&\n getEventState(event) === \"submitted\");\n const transactionConfirmed = hasCompletedType(events, steps, [\n \"TRANSACTION_CONFIRMED\",\n ]);\n const rows: ProgressStatusRow[] = [];\n\n const pushRow = (row: ProgressStatusRow) => {\n if (failedStatus) {\n const failedIndex = STATUS_ORDER.indexOf(failedStatus);\n const currentIndex = STATUS_ORDER.indexOf(row.id);\n if (failedIndex >= 0 && currentIndex > failedIndex) return;\n }\n rows.push(row);\n };\n\n if (approvalTotal > 0) {\n const approvalCurrent = Math.min(\n approvalTotal,\n Math.max(1, approvalCompletedCount + 1),\n );\n const symbols = formatSymbolSummary(approval.symbols);\n const approvalDescription = symbols\n ? `${approval.permitsOnly ? \"Sign permit for\" : \"Approve\"} ${symbols} in wallet`\n : \"Approve in wallet\";\n const state: ProgressStatusState = failedStatus === \"approveTokens\"\n ? \"error\"\n : approvalCompletedCount >= approvalTotal\n ? \"completed\"\n : approval.awaitingWallet ? \"preapproval\" : \"default\";\n\n pushRow({\n id: \"approveTokens\",\n state,\n description: state === \"preapproval\" ? approvalDescription : undefined,\n label:\n state === \"completed\"\n ? `Tokens approved for swap (${approvalTotal} of ${approvalTotal})`\n : state === \"error\"\n ? \"Token approval failed\"\n : `Approve tokens for swap (${approvalCurrent} of ${approvalTotal})`,\n });\n }\n\n if (shouldShowSwapRows) {\n const approvalsSatisfied = !approval.blocksSwapExecution;\n let state: ProgressStatusState = \"default\";\n if (failedStatus === \"swapTokens\") {\n state = \"error\";\n } else if (swapTokensComplete) {\n state = \"completed\";\n } else if (\n approvalsSatisfied &&\n (hasStartedStatus(events, \"swapTokens\", mode, hasTransferAction) ||\n hasEventType(events, [\n \"DESTINATION_SWAP_BATCH_TX\",\n \"BRIDGE_DEPOSIT\",\n \"SOURCE_SWAP_BATCH_TX\",\n \"SOURCE_SWAP_HASH\",\n \"SWAP_START\",\n ]))\n ) {\n state = \"inProgress\";\n }\n\n pushRow({\n id: \"swapTokens\",\n state,\n label:\n state === \"completed\"\n ? \"Swaps completed\"\n : state === \"error\"\n ? refundEligibleFailure\n ? \"Swap failed. Refund initiated\"\n : \"Swap failed\"\n : state === \"inProgress\"\n ? \"Swaps in progress\"\n : \"Swap tokens\",\n });\n\n if (hasReceiveTokenStep) {\n pushRow({\n id: \"receiveToken\",\n state:\n failedStatus === \"receiveToken\"\n ? \"error\"\n : receiveTokenComplete\n ? \"completed\"\n : receiveTokenStarted\n ? \"inProgress\"\n : \"default\",\n label:\n failedStatus === \"receiveToken\"\n ? refundEligibleFailure\n ? \"Destination swap failed. Refund initiated.\"\n : \"Destination swap failed.\"\n : receiveTokenComplete\n ? `Received ${destinationSymbol} on ${destinationChain}`\n : receiveTokenStarted\n ? `Receiving ${destinationSymbol} on ${destinationChain}`\n : `Receive ${destinationSymbol} on ${destinationChain}`,\n });\n }\n }\n\n if (mode === \"deposit\" || hasTransferAction) {\n const receiveComplete =\n swapSkipped ||\n !shouldShowSwapRows ||\n (hasReceiveTokenStep ? receiveTokenComplete : swapTokensComplete);\n const isDeposit = mode === \"deposit\";\n let state: ProgressStatusState = \"default\";\n if (failedStatus === \"action\") {\n state = \"error\";\n } else if (transactionConfirmed) {\n state = \"completed\";\n } else if (transactionSent) {\n state = \"inProgress\";\n } else if (receiveComplete) {\n state = \"preapproval\";\n }\n\n pushRow({\n id: \"action\",\n state,\n description: state === \"preapproval\" ? \"Approve in wallet\" : undefined,\n label: isDeposit\n ? state === \"completed\"\n ? `${destinationSymbol} deposited to ${opportunityName}`\n : state === \"inProgress\"\n ? `Depositing ${destinationSymbol} to ${opportunityName}`\n : state === \"error\"\n ? \"Deposit failed. Funds are in your wallet.\"\n : state === \"preapproval\"\n ? `Approve Deposit of ${destinationSymbol} to ${opportunityName}`\n : `Deposit ${destinationSymbol} to ${opportunityName}`\n : state === \"completed\"\n ? `${destinationSymbol} sent`\n : state === \"inProgress\"\n ? `Sending ${destinationSymbol}`\n : state === \"error\"\n ? \"Send failed. Funds are in your wallet.\"\n : state === \"preapproval\"\n ? `Approve ${destinationSymbol} transfer`\n : `Send ${destinationSymbol}`,\n });\n }\n\n const orderedRows = rows.sort(\n (a, b) => STATUS_ORDER.indexOf(a.id) - STATUS_ORDER.indexOf(b.id),\n );\n\n if (\n orderedRows.some(\n (row) => row.state === \"preapproval\" || row.state === \"inProgress\",\n ) ||\n orderedRows.some((row) => row.state === \"error\")\n ) {\n return orderedRows;\n }\n\n const nextActiveIndex = orderedRows.findIndex(\n (row) => row.state === \"default\",\n );\n if (nextActiveIndex === -1) return orderedRows;\n\n return orderedRows.map((row, index) => {\n if (index !== nextActiveIndex) return row;\n const nextState =\n row.id === \"approveTokens\" || row.id === \"action\"\n ? \"preapproval\"\n : \"inProgress\";\n return {\n ...row,\n description:\n nextState === \"preapproval\" ? \"Approve in wallet\" : undefined,\n label:\n row.id === \"swapTokens\"\n ? \"Swaps in progress\"\n : row.id === \"receiveToken\"\n ? `Receiving ${destinationSymbol} on ${destinationChain}`\n : row.label,\n state: nextState,\n };\n });\n};\n\nfunction MiniLogo({\n src,\n label,\n size,\n style,\n}: {\n src?: string;\n label?: string;\n size: number;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n background: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").trim().slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction TokenLogoPair({\n tokenLogo,\n chainLogo,\n tokenSymbol,\n chainName,\n}: {\n tokenLogo?: string;\n chainLogo?: string;\n tokenSymbol?: string;\n chainName?: string;\n}) {\n return (\n \n \n {chainLogo && (\n \n )}\n \n );\n}\n\nexport function NexusWidgetProgressScreen({\n fromTokens = [],\n toToken,\n fromAmountUsd,\n toAmount,\n toAmountUsd,\n totalFeeUsd,\n intentData,\n mode,\n opportunity,\n steps,\n progressEvents = [],\n failedStep,\n recipientAddress,\n}: NexusWidgetProgressScreenProps) {\n const intentSources = intentData?.sources ?? [];\n const intentDestination = intentData?.destination;\n const destinationSourceToken = fromTokens.find((token) => {\n const destinationChainId = intentDestination?.chain.id ?? toToken?.chainId;\n const destinationTokenAddress = (\n intentDestination?.token.contractAddress ??\n toToken?.contractAddress ??\n \"\"\n ).toLowerCase();\n const tokenAmount =\n parseDecimal(token.userAmount) ?? parseDecimal(token.balance);\n\n return (\n destinationChainId !== undefined &&\n destinationTokenAddress !== \"\" &&\n token.chainId === destinationChainId &&\n token.contractAddress.toLowerCase() === destinationTokenAddress &&\n Boolean(tokenAmount && tokenAmount.gt(0))\n );\n });\n const sourceSymbols = unique([\n ...(destinationSourceToken ? [destinationSourceToken.symbol] : []),\n ...(intentSources.length > 0\n ? intentSources.map((source) => source.token.symbol)\n : fromTokens.map((token) => token.symbol)),\n ]);\n const intentSourceUsd =\n intentSources.length > 0\n ? intentSources.reduce(\n (sum, source) => sum.plus(parseDecimal(source.value) ?? 0),\n new Decimal(0),\n )\n : parseDecimal(fromAmountUsd);\n const requestedDestinationAmount = parseDecimal(toAmount);\n const quotedDestinationAmount = parseDecimal(intentDestination?.amount);\n const destinationBalanceAmount = parseDecimal(toToken?.balance);\n const requestedDestinationUsd = parseDecimal(toAmountUsd);\n const destinationUsdRate =\n requestedDestinationAmount &&\n requestedDestinationAmount.gt(0) &&\n requestedDestinationUsd &&\n requestedDestinationUsd.gt(0)\n ? requestedDestinationUsd.div(requestedDestinationAmount)\n : quotedDestinationAmount &&\n quotedDestinationAmount.gt(0) &&\n intentDestination?.value\n ? (parseDecimal(intentDestination.value) ?? new Decimal(0)).div(\n quotedDestinationAmount,\n )\n : undefined;\n const destinationCoverageUsd =\n (mode === \"deposit\" || mode === \"send\") &&\n requestedDestinationAmount &&\n requestedDestinationAmount.gt(0) &&\n quotedDestinationAmount &&\n requestedDestinationAmount.gt(quotedDestinationAmount) &&\n destinationBalanceAmount &&\n destinationBalanceAmount.gt(0) &&\n destinationUsdRate &&\n destinationUsdRate.gt(0)\n ? Decimal.min(\n requestedDestinationAmount.minus(quotedDestinationAmount),\n destinationBalanceAmount,\n ).mul(destinationUsdRate)\n : undefined;\n const quotedDestinationUsd = parseDecimal(intentDestination?.value);\n const feeUsd = parseDecimal(totalFeeUsd);\n const sourceUsd =\n mode === \"deposit\" || mode === \"send\"\n ? [\n destinationCoverageUsd !== undefined\n ? (intentSourceUsd ?? new Decimal(0)).plus(destinationCoverageUsd)\n : intentSourceUsd,\n requestedDestinationUsd,\n requestedDestinationUsd &&\n requestedDestinationUsd.gt(0) &&\n intentSourceUsd &&\n intentSourceUsd.gt(0) &&\n quotedDestinationUsd &&\n quotedDestinationUsd.gt(0)\n ? requestedDestinationUsd.plus(\n Decimal.max(intentSourceUsd.minus(quotedDestinationUsd), 0),\n )\n : undefined,\n requestedDestinationUsd &&\n requestedDestinationUsd.gt(0) &&\n feeUsd &&\n feeUsd.gt(0)\n ? requestedDestinationUsd.plus(feeUsd)\n : undefined,\n ]\n .filter((value): value is Decimal => Boolean(value && value.gt(0)))\n .reduce(\n (max, value) => (!max || value.gt(max) ? value : max),\n undefined,\n )\n : intentSourceUsd;\n const destinationAmount =\n (mode === \"deposit\" || mode === \"send\") && toAmount\n ? toAmount\n : (intentDestination?.amount ?? toAmount ?? \"0\");\n const destinationSymbol =\n intentDestination?.token.symbol ||\n toToken?.symbol ||\n opportunity?.tokenSymbol ||\n \"\";\n const destinationChainName = getShortChainName(\n intentDestination?.chain.id ?? toToken?.chainId,\n intentDestination?.chain.name || toToken?.chainName || \"\",\n );\n const destinationChain =\n mode === \"deposit\"\n ? opportunity?.title || opportunity?.protocol || destinationChainName\n : destinationChainName;\n const statusRows = buildStatusRows({\n events: progressEvents,\n failedStep,\n mode,\n steps: steps ?? [],\n context: {\n destinationChain: destinationChainName || destinationChain,\n destinationSymbol,\n opportunityName: opportunity?.title || opportunity?.protocol,\n recipientAddress,\n },\n });\n const [stepsExpanded, setStepsExpanded] = useState(true);\n const activeRow =\n statusRows.find(\n (row) => row.state === \"preapproval\" || row.state === \"inProgress\",\n ) ??\n statusRows.find((row) => row.state === \"error\") ??\n statusRows.find((row) => row.state === \"default\") ??\n statusRows[statusRows.length - 1];\n const visibleRows = stepsExpanded ? statusRows : activeRow ? [activeRow] : [];\n const canExpand = statusRows.length > 1;\n const getRowHeight = (row: ProgressStatusRow) => (row.description ? 47 : 40);\n const collapsedStatusHeight = activeRow ? getRowHeight(activeRow) : 40;\n const expandedStatusHeight = statusRows.reduce(\n (sum, row) => sum + getRowHeight(row),\n 0,\n );\n\n return (\n \n \n \n {formatSymbolSummary(sourceSymbols)}\n \n \n {formatUsd(sourceUsd)}\n \n\n \n\n \n \n \n {formatDecimal(destinationAmount, 8)}\n \n {destinationSymbol}\n \n \n {destinationChain && (\n \n on {destinationChain}\n \n )}\n \n \n\n \n \n \n {visibleRows.map((row, index) => {\n const isCompleted = row.state === \"completed\";\n const isError = row.state === \"error\";\n const isDefault = row.state === \"default\";\n const isLoading =\n row.state === \"preapproval\" || row.state === \"inProgress\";\n const hasDescription = Boolean(row.description);\n const rowColor = isDefault ? muted : isError ? danger : primary;\n\n return (\n {\n if (canExpand) setStepsExpanded((current) => !current);\n }}\n style={{\n alignItems: hasDescription ? \"flex-start\" : \"center\",\n appearance: \"none\",\n background: \"transparent\",\n border: \"0\",\n borderTop:\n index > 0 && stepsExpanded ? `1px solid ${border}` : \"0\",\n boxSizing: \"border-box\",\n color: rowColor,\n cursor: canExpand ? \"pointer\" : \"default\",\n display: \"flex\",\n fontFamily,\n fontSize: \"11px\",\n fontWeight: 400,\n gap: \"7px\",\n minHeight: `${getRowHeight(row)}px`,\n padding: \"8px 11px\",\n textAlign: \"left\",\n transition:\n \"color 220ms ease, min-height 220ms ease, opacity 220ms ease\",\n width: \"100%\",\n }}\n type=\"button\"\n >\n {isCompleted || isError ? (\n \n {isError ? (\n \n ) : (\n \n )}\n \n ) : isDefault ? (\n \n ) : (\n\t \n )}\n \n \n {row.label}\n \n {row.description && (\n \n {row.description}\n \n )}\n \n {canExpand && index === 0 && (\n \n )}\n \n );\n })}\n \n \n \n \n );\n}\n", "type": "registry:component", "target": "components/nexus/components/nexus-widget-progress-screen.tsx" }, + { + "path": "registry/avail-widgets/nexus-widget/components/onramp-history-card.tsx", + "content": "import React from \"react\";\nimport Decimal from \"decimal.js\";\nimport { CreditCard, ExternalLink } from \"lucide-react\";\nimport { nexusWidgetTheme as theme } from \"../theme\";\nimport { getNormalizedOnrampState, isOnrampTerminalState } from \"../utils/onramp-session\";\nimport type { OnrampHistoryEntry } from \"../utils/onramp-history\";\n\nconst displayName = (value?: string) => value?.split(/[_\\s-]+/)\n .filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1).toLowerCase()).join(\" \");\n\nconst tokenAmount = (value?: string) => {\n if (value == null) return \"—\";\n try {\n const amount = new Decimal(value);\n return amount.isFinite() && amount.gte(0)\n ? amount.toDecimalPlaces(8, Decimal.ROUND_DOWN).toFixed() : \"—\";\n } catch { return \"—\"; }\n};\n\nexport function OnrampHistoryCard({\n entry, relativeTime, chainName, explorerUrl,\n}: { entry: OnrampHistoryEntry; relativeTime: string; chainName?: string; explorerUrl?: string | null }) {\n const { session, context } = entry;\n const transaction = session.transaction;\n const state = getNormalizedOnrampState(session.state);\n const settled = state === \"SETTLED\";\n const pending = !isOnrampTerminalState(state);\n const status = settled ? \"Completed\" : pending ? \"Pending\"\n : state === \"REFUNDED\" ? \"Refunded\" : state === \"CANCELLED\" ? \"Cancelled\"\n : [\"EXPIRED\", \"AUTHORIZATION_EXPIRED\"].includes(state) ? \"Expired\" : \"Failed\";\n const provider = displayName(session.provider ?? context.provider) ?? \"Payment partner\";\n const method = session.paymentMethodType ?? context.paymentMethodType;\n const amount = transaction?.destinationAmount ?? context.destinationAmount;\n const symbol = context.tokenSymbol ?? transaction?.destinationCurrencyCode ?? \"tokens\";\n const fiatAmount = transaction?.sourceAmount ?? context.sourceAmount;\n const fiatCurrency = transaction?.sourceCurrencyCode ?? context.sourceCurrencyCode;\n const fg = settled ? \"#168A47\" : pending ? \"#B7791F\" : \"#E92C2C\";\n const bg = settled ? \"#E8F6EF\" : pending ? \"#FFF3DE\" : \"#FFE6EA\";\n return (\n
\n
\n
\n \n
\n
Onramp · {provider}
\n
\n {tokenAmount(amount)} {symbol}\n
\n
\n {settled && transaction?.destinationAmount ? \"Received\" : transaction?.destinationAmount ? \"Tokens\" : \"Estimated\"}\n {chainName ? ` on ${chainName}` : \"\"}\n
\n
\n
\n
\n \n {status}\n \n
{relativeTime}
\n
\n
\n
\n
\n \n {settled && transaction?.sourceAmount != null ? \"Fiat spent\" : \"Fiat amount\"}: {fiatAmount && fiatCurrency ? `${fiatAmount} ${fiatCurrency}` : \"—\"}\n {fiatAmount && transaction?.sourceAmount == null ? \" (quoted)\" : \"\"}\n \n {explorerUrl && \n View transaction \n }\n
\n {method &&
Payment method: {displayName(method)}
}\n {pending &&
Payment status refreshes while history is open.
}\n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/nexus/components/onramp-history-card.tsx" + }, { "path": "registry/avail-widgets/nexus-widget/components/pay-using-selector.tsx", "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport { Pencil, Settings } from \"lucide-react\";\nimport React from \"react\";\nimport { nexusWidgetTheme } from \"../theme\";\n\nexport interface PayUsingSelectorProps {\n disabled?: boolean;\n hasSources?: boolean;\n label?: string;\n onClick?: () => void;\n sublabel?: string;\n}\n\nexport function PayUsingSelector({\n label = \"Paying with\",\n sublabel = \"Auto-selected based on amount\",\n onClick,\n disabled = false,\n hasSources = false,\n}: PayUsingSelectorProps) {\n const isInteractiveRow = !hasSources;\n\n const content = (\n <>\n
\n \n \n
\n
\n \n {label}\n \n \n {sublabel}\n \n
\n \n\n {/* Edit button */}\n {!isInteractiveRow && (\n {\n e.stopPropagation();\n onClick?.();\n }}\n style={{\n fontFamily: \"var(--font-geist-sans), sans-serif\",\n fontSize: \"13px\",\n fontWeight: 500,\n color:\n \"var(--interactive-button-primary-background, var(--foreground-brand))\",\n }}\n >\n \n Edit\n \n )}\n \n );\n\n return (\n
\n {isInteractiveRow ? (\n \n {content}\n \n ) : (\n \n {content}\n
\n )}\n \n );\n}\n", @@ -50,7 +68,7 @@ }, { "path": "registry/avail-widgets/nexus-widget/components/pay-with-sources.tsx", - "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport Decimal from \"decimal.js\";\nimport { AlertCircle, ChevronDown, Loader2 } from \"lucide-react\";\nimport React, { useRef, useState } from \"react\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport { type SwapTokenOption } from \"./swap-asset-selector\";\n\nconst uiFont = '\"Geist\", system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\n\nconst formatToken = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst formatUsd = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n return `$${amount.toDecimalPlaces(2).toFixed()}`;\n};\n\nconst getDisplayedUsdValue = (token: SwapTokenOption) =>\n parseDecimal(token.userAmountUsd || token.balanceInFiat) ?? new Decimal(0);\n\nconst sortSourceTokensByDisplayedUsdDesc = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const usdDiff = getDisplayedUsdValue(b).cmp(getDisplayedUsdValue(a));\n if (usdDiff !== 0) return usdDiff;\n return `${a.symbol ?? \"\"} ${a.chainName ?? \"\"}`.localeCompare(\n `${b.symbol ?? \"\"} ${b.chainName ?? \"\"}`,\n );\n });\n\nfunction TokenLogo({\n src,\n label,\n size = 30,\n fontSize = 12,\n style,\n}: {\n src?: string;\n label?: string;\n size?: number;\n fontSize?: number;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n React.useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction SourceLogoPair({ token }: { token: SwapTokenOption }) {\n return (\n
\n \n {token.chainLogo && (\n \n )}\n
\n );\n}\n\nfunction SkeletonRow() {\n return (\n \n \n \n \n );\n}\n\nexport function PayWithSources({\n fromTokens,\n onOpenSourcePicker,\n routeStatus,\n routeMessage,\n showAutoBadge = true,\n isSourcePickerDisabled = false,\n reserveSourceRows = false,\n}: {\n fromTokens: SwapTokenOption[];\n onOpenSourcePicker: () => void;\n routeStatus?: \"loading\" | \"insufficient\";\n routeMessage?: string;\n showAutoBadge?: boolean;\n isSourcePickerDisabled?: boolean;\n reserveSourceRows?: boolean;\n}) {\n const scrollRef = useRef(null);\n const isRouteLoading = routeStatus === \"loading\";\n const displayTokens = React.useMemo(\n () => sortSourceTokensByDisplayedUsdDesc(fromTokens),\n [fromTokens],\n );\n const shouldShowSourceSummary = !isRouteLoading && displayTokens.length > 0;\n const shouldScroll = shouldShowSourceSummary && displayTokens.length > 3;\n const sourceCountLabel =\n displayTokens.length === 1 ? \"1 asset\" : `${displayTokens.length} assets`;\n const autoBadge = (\n \n AUTO\n \n );\n\n return (\n \n \n \n \n Pay With\n {shouldShowSourceSummary ? ` · ${sourceCountLabel}` : \"\"}\n \n {showAutoBadge ? autoBadge : null}\n \n {shouldShowSourceSummary && (\n \n Edit tokens\n \n )}\n \n\n {isRouteLoading ? (\n <>\n \n \n \n Calculating best route...\n \n \n ) : shouldShowSourceSummary ? (\n
\n \n {displayTokens.map((token, index) => (\n \n \n \n \n \n \n {token.symbol}\n \n \n {token.isUnified\n ? \"Unified balance\"\n : `on ${token.chainName || \"Unknown chain\"}`}\n \n
\n \n \n \n \n {formatToken(token.userAmount || token.balance)}{\" \"}\n {token.symbol}\n \n \n {formatUsd(token.userAmountUsd || token.balanceInFiat)}\n \n \n \n ))}\n \n {shouldScroll && (\n \n scrollRef.current?.scrollBy({ behavior: \"smooth\", top: 64 })\n }\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${border}`,\n borderRadius: \"999px\",\n bottom: \"4px\",\n boxShadow: \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n cursor: \"pointer\",\n display: \"flex\",\n height: \"22px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"22px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n ) : (\n \n Sources will be auto selected\n \n )}\n\n {routeStatus === \"insufficient\" && routeMessage && (\n \n \n {routeMessage}\n \n )}\n \n );\n}\n", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport Decimal from \"decimal.js\";\nimport { AlertCircle, ChevronDown, Loader2 } from \"lucide-react\";\nimport React, { useRef, useState } from \"react\";\nimport { NEXUS_WIDGET_FAST_SPINNER_STYLE } from \"../theme\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport { type SwapTokenOption } from \"./swap-asset-selector\";\n\nconst uiFont = '\"Geist\", system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\n\nconst formatToken = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst formatUsd = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n return `$${amount.toDecimalPlaces(2).toFixed()}`;\n};\n\nconst getDisplayedUsdValue = (token: SwapTokenOption) =>\n parseDecimal(token.userAmountUsd || token.balanceInFiat) ?? new Decimal(0);\n\nconst sortSourceTokensByDisplayedUsdDesc = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const usdDiff = getDisplayedUsdValue(b).cmp(getDisplayedUsdValue(a));\n if (usdDiff !== 0) return usdDiff;\n return `${a.symbol ?? \"\"} ${a.chainName ?? \"\"}`.localeCompare(\n `${b.symbol ?? \"\"} ${b.chainName ?? \"\"}`,\n );\n });\n\nfunction TokenLogo({\n src,\n label,\n size = 30,\n fontSize = 12,\n style,\n}: {\n src?: string;\n label?: string;\n size?: number;\n fontSize?: number;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n React.useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction SourceLogoPair({ token }: { token: SwapTokenOption }) {\n return (\n
\n \n {token.chainLogo && (\n \n )}\n
\n );\n}\n\nfunction SkeletonRow() {\n return (\n \n \n \n \n );\n}\n\nexport function PayWithSources({\n fromTokens,\n onOpenSourcePicker,\n routeStatus,\n routeMessage,\n showAutoBadge = true,\n isSourcePickerDisabled = false,\n reserveSourceRows = false,\n}: {\n fromTokens: SwapTokenOption[];\n onOpenSourcePicker: () => void;\n routeStatus?: \"loading\" | \"insufficient\";\n routeMessage?: string;\n showAutoBadge?: boolean;\n isSourcePickerDisabled?: boolean;\n reserveSourceRows?: boolean;\n}) {\n const scrollRef = useRef(null);\n const isRouteLoading = routeStatus === \"loading\";\n const displayTokens = React.useMemo(\n () => sortSourceTokensByDisplayedUsdDesc(fromTokens),\n [fromTokens],\n );\n const shouldShowSourceSummary = !isRouteLoading && displayTokens.length > 0;\n const shouldScroll = shouldShowSourceSummary && displayTokens.length > 3;\n const sourceCountLabel =\n displayTokens.length === 1 ? \"1 asset\" : `${displayTokens.length} assets`;\n const autoBadge = (\n \n AUTO\n \n );\n\n return (\n \n \n \n \n Pay With\n {shouldShowSourceSummary ? ` · ${sourceCountLabel}` : \"\"}\n \n {showAutoBadge ? autoBadge : null}\n \n {shouldShowSourceSummary && (\n \n Edit tokens\n \n )}\n \n\n {isRouteLoading ? (\n <>\n \n \n \n Calculating best route...\n \n \n ) : shouldShowSourceSummary ? (\n
\n \n {displayTokens.map((token, index) => (\n \n \n \n \n \n \n {token.symbol}\n \n \n {token.isUnified\n ? \"Unified balance\"\n : `on ${token.chainName || \"Unknown chain\"}`}\n \n
\n \n \n \n \n {formatToken(token.userAmount || token.balance)}{\" \"}\n {token.symbol}\n \n \n {formatUsd(token.userAmountUsd || token.balanceInFiat)}\n \n \n \n ))}\n \n {shouldScroll && (\n \n scrollRef.current?.scrollBy({ behavior: \"smooth\", top: 64 })\n }\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${border}`,\n borderRadius: \"999px\",\n bottom: \"4px\",\n boxShadow:\n \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n cursor: \"pointer\",\n display: \"flex\",\n height: \"22px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"22px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n ) : (\n \n Sources will be auto selected\n \n )}\n\n {routeStatus === \"insufficient\" && routeMessage && (\n \n \n {routeMessage}\n \n )}\n \n );\n}\n", "type": "registry:component", "target": "components/nexus/components/pay-with-sources.tsx" }, @@ -68,7 +86,7 @@ }, { "path": "registry/avail-widgets/nexus-widget/components/send-idle-form.tsx", - "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport Decimal from \"decimal.js\";\nimport { AlertCircle, ChevronDown, Loader2 } from \"lucide-react\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport { useNexusWidgetThemeStyle } from \"../theme-context\";\nimport React, { useRef, useState } from \"react\";\nimport { PayWithSources as SharedPayWithSources } from \"./pay-with-sources\";\nimport {\n formatSelectedTokenBalanceLabel,\n type SwapTokenOption,\n} from \"./swap-asset-selector\";\n\ninterface SendIdleFormProps {\n amount: string;\n calculatingPercent?: number | null;\n fromTokens: SwapTokenOption[];\n isAmountReadOnly?: boolean;\n isAssetPickerDisabled?: boolean;\n isBalanceLoading?: boolean;\n isCalculatingMax?: boolean;\n isQuoteRefreshing?: boolean;\n isRecipientLocked?: boolean;\n hideDestinationTokenDropdownIcon?: boolean;\n isSourcePickerDisabled?: boolean;\n onAmountChange: (val: string) => void;\n onOpenAssetPicker: () => void;\n onOpenRecipientPicker: () => void;\n onOpenSourcePicker: () => void;\n onSetPercent: (pct: number) => void;\n recipientAddress: string;\n reserveSourceRows?: boolean;\n routeMessage?: string;\n routeStatus?: \"loading\" | \"insufficient\";\n showAutoBadge?: boolean;\n toToken?: SwapTokenOption;\n totalBalance: string;\n usdValue: string;\n}\n\nconst uiFont = '\"Geist\", system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\n\nconst formatToken = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst formatUsd = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n return `$${amount.toDecimalPlaces(2).toFixed()}`;\n};\n\nconst MAX_AMOUNT_DISPLAY_DECIMALS = 8;\nconst getTokenInputDecimals = (token?: Pick) => {\n const decimals = Number(token?.decimals);\n return Number.isFinite(decimals) && decimals >= 0 ? Math.floor(decimals) : 18;\n};\n\nconst formatAmountInputDisplay = (value: string) => {\n if (!value) return \"\";\n try {\n return new Decimal(value)\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n } catch {\n return value;\n }\n};\n\nconst sanitizeAmountInput = (raw: string, maxDecimals: number) => {\n let next = raw.replaceAll(/[^0-9.]/g, \"\");\n const parts = next.split(\".\");\n if (parts.length > 2) next = parts[0] + \".\" + parts.slice(1).join(\"\");\n const [integerPart, decimalPart] = next.split(\".\");\n if (decimalPart !== undefined) {\n next = `${integerPart}.${decimalPart.slice(0, Math.max(0, maxDecimals))}`;\n }\n if (next === \".\") next = \"0.\";\n return next;\n};\n\nfunction TokenLogo({\n src,\n label,\n size = 30,\n fontSize = 12,\n style,\n}: {\n src?: string;\n label?: string;\n size?: number;\n fontSize?: number;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n React.useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction SourceLogoPair({ token }: { token: SwapTokenOption }) {\n return (\n
\n \n {token.chainLogo && (\n \n )}\n
\n );\n}\n\nfunction ExactOutPercentButtons({\n visible,\n onSelect,\n selectedPercent,\n}: {\n visible: boolean;\n onSelect: (pct: number) => void;\n selectedPercent: number | null;\n}) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [focusedPercent, setFocusedPercent] = useState(null);\n\n React.useEffect(() => {\n if (!visible) setFocusedPercent(null);\n }, [visible]);\n\n return (\n \n {[25, 50, 75, 100].map((pct) => {\n const isMax = pct === 100;\n const isFocused = focusedPercent === pct;\n return (\n {\n e.stopPropagation();\n onSelect(pct);\n }}\n onBlur={() => setFocusedPercent(null)}\n onFocus={() => setFocusedPercent(pct)}\n style={{\n alignItems: \"center\",\n backgroundColor: isFocused ? \"var(--nexus-widget-primary-soft, #E8F0FF)\" : \"var(--nexus-widget-surface-raised, #F4F4F3)\",\n border: \"none\",\n borderRadius: \"8px\",\n boxSizing: \"border-box\",\n color: isFocused ? brand : \"var(--nexus-widget-text, #363635)\",\n cursor: \"pointer\",\n display: \"flex\",\n flex: \"1 1 0%\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"12px\",\n fontWeight: 500,\n justifyContent: \"center\",\n lineHeight: \"20px\",\n minWidth: 0,\n paddingBlock: \"5px\",\n paddingInline: \"10px\",\n }}\n type=\"button\"\n >\n {isMax ? \"MAX\" : `${pct}%`}\n \n );\n })}\n \n );\n}\n\nfunction SkeletonRow() {\n return (\n \n \n \n \n );\n}\n\nfunction PayWithSources({\n fromTokens,\n onOpenSourcePicker,\n routeStatus,\n routeMessage,\n}: {\n fromTokens: SwapTokenOption[];\n onOpenSourcePicker: () => void;\n routeStatus?: \"loading\" | \"insufficient\";\n routeMessage?: string;\n}) {\n const scrollRef = useRef(null);\n const isRouteLoading = routeStatus === \"loading\";\n const shouldShowSourceSummary = !isRouteLoading && fromTokens.length > 0;\n const shouldScroll = shouldShowSourceSummary && fromTokens.length > 3;\n const autoBadge = (\n \n AUTO\n \n );\n\n return (\n \n \n \n \n Pay With\n {shouldShowSourceSummary ? ` · ${fromTokens.length} assets` : \"\"}\n \n {autoBadge}\n \n {shouldShowSourceSummary && (\n \n Edit tokens\n \n )}\n \n\n {isRouteLoading ? (\n <>\n \n \n \n Calculating best route...\n \n \n ) : shouldShowSourceSummary ? (\n
\n \n {fromTokens.map((token, index) => (\n \n \n \n \n \n {token.symbol}\n \n \n {token.isUnified\n ? \"Unified balance\"\n : `on ${token.chainName || \"Unknown chain\"}`}\n \n
\n \n \n \n {formatToken(token.userAmount || token.balance)}{\" \"}\n {token.symbol}\n \n \n {formatUsd(token.userAmountUsd || token.balanceInFiat)}\n \n \n \n ))}\n \n {shouldScroll && (\n \n scrollRef.current?.scrollBy({ behavior: \"smooth\", top: 64 })\n }\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${border}`,\n borderRadius: \"999px\",\n bottom: \"4px\",\n boxShadow: \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n cursor: \"pointer\",\n display: \"flex\",\n height: \"22px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"22px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n ) : (\n \n Sources will be auto selected\n \n )}\n\n {routeStatus === \"insufficient\" && routeMessage && (\n \n \n {routeMessage}\n \n )}\n \n );\n}\n\nfunction BalanceSkeleton({\n height = \"16px\",\n width = \"72px\",\n}: {\n height?: string;\n width?: string;\n}) {\n return (\n \n );\n}\n\nexport function SendIdleForm({\n amount,\n onAmountChange,\n toToken,\n fromTokens,\n totalBalance,\n usdValue,\n onOpenAssetPicker,\n onOpenSourcePicker,\n onOpenRecipientPicker,\n recipientAddress,\n onSetPercent,\n routeStatus,\n routeMessage,\n isAmountReadOnly = false,\n isAssetPickerDisabled = false,\n isBalanceLoading = false,\n isCalculatingMax,\n calculatingPercent,\n isQuoteRefreshing,\n isRecipientLocked = false,\n hideDestinationTokenDropdownIcon = false,\n showAutoBadge = true,\n isSourcePickerDisabled = false,\n reserveSourceRows = false,\n}: SendIdleFormProps) {\n const [selectedPercent, setSelectedPercent] = useState(null);\n const [pendingPercent, setPendingPercent] = useState(null);\n const [isAmountFocused, setIsAmountFocused] = useState(false);\n\n React.useEffect(() => {\n if (!isCalculatingMax) setPendingPercent(null);\n }, [isCalculatingMax]);\n\n React.useEffect(() => {\n setSelectedPercent(null);\n }, [toToken?.contractAddress, toToken?.chainId]);\n\n const handlePercentSelect = (pct: number) => {\n setSelectedPercent(pct);\n setPendingPercent(pct);\n onSetPercent(pct);\n };\n\n const handleInput = (e: React.ChangeEvent) => {\n if (isAmountReadOnly) return;\n setSelectedPercent(null);\n onAmountChange(\n sanitizeAmountInput(e.target.value, getTokenInputDecimals(toToken)),\n );\n };\n const amountDisplayValue = isAmountFocused\n ? amount\n : formatAmountInputDisplay(amount);\n const activePendingPercent =\n calculatingPercent ?? (isCalculatingMax ? pendingPercent : null);\n const isMaxCalculating = Boolean(\n isCalculatingMax && activePendingPercent === 100,\n );\n\n const destinationBalanceLabel =\n formatSelectedTokenBalanceLabel(toToken) ||\n `0 ${toToken?.symbol || \"\"}`.trim();\n\n return (\n \n \n \n \n Recipient\n \n \n \n {recipientAddress\n ? `${recipientAddress.slice(0, 6)}…${recipientAddress.slice(-4)}`\n : \"Select recipient\"}\n \n \n \n {isRecipientLocked ? \"Locked\" : \"Edit\"}\n \n \n \n \n \n\n \n \n \n Amount\n \n
\n \n Total Balance:\n \n \n {isBalanceLoading ? (\n \n ) : (\n `$${totalBalance}`\n )}\n \n
\n \n\n
\n \n {isMaxCalculating ? (\n \n ) : (\n setIsAmountFocused(false)}\n onChange={handleInput}\n onFocus={() => setIsAmountFocused(true)}\n placeholder=\"0\"\n style={{\n background: \"transparent\",\n border: \"none\",\n boxSizing: \"border-box\",\n color: amount ? primary : \"var(--nexus-widget-text-tertiary, #C8C8C6)\",\n cursor: isAmountReadOnly ? \"default\" : \"text\",\n flex: \"1 1 0%\",\n fontFamily:\n '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"36px\",\n fontWeight: 500,\n lineHeight: \"44px\",\n minWidth: 0,\n outline: \"none\",\n padding: 0,\n }}\n readOnly={isAmountReadOnly}\n type=\"text\"\n value={amountDisplayValue}\n />\n )}\n {isCalculatingMax && !isMaxCalculating && (\n \n )}\n\n \n {toToken ? (\n \n \n {toToken.chainLogo && (\n \n )}\n
\n ) : (\n \n )}\n \n {toToken ? toToken.symbol : \"Assets\"}\n \n {!hideDestinationTokenDropdownIcon && (\n \n )}\n \n \n\n \n \n \n ≈ ${usdValue || \"0\"}\n \n \n\n \n {toToken && (\n <>\n \n Balance:\n \n \n {isBalanceLoading ? (\n \n ) : (\n destinationBalanceLabel\n )}\n \n \n )}\n \n \n\n \n \n \n\n \n \n );\n}\n", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport Decimal from \"decimal.js\";\nimport { AlertCircle, ChevronDown, Loader2 } from \"lucide-react\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport { useNexusWidgetThemeStyle } from \"../theme-context\";\nimport React, { useRef, useState } from \"react\";\nimport { PayWithSources as SharedPayWithSources } from \"./pay-with-sources\";\nimport { NEXUS_WIDGET_FAST_SPINNER_STYLE } from \"../theme\";\nimport {\n formatSelectedTokenBalanceLabel,\n type SwapTokenOption,\n} from \"./swap-asset-selector\";\n\ninterface SendIdleFormProps {\n amount: string;\n calculatingPercent?: number | null;\n fromTokens: SwapTokenOption[];\n isAmountReadOnly?: boolean;\n isAssetPickerDisabled?: boolean;\n isBalanceLoading?: boolean;\n isCalculatingMax?: boolean;\n isQuoteRefreshing?: boolean;\n isRecipientLocked?: boolean;\n hideDestinationTokenDropdownIcon?: boolean;\n isSourcePickerDisabled?: boolean;\n onAmountChange: (val: string) => void;\n onOpenAssetPicker: () => void;\n onOpenRecipientPicker: () => void;\n onOpenSourcePicker: () => void;\n onSetPercent: (pct: number) => void;\n recipientAddress: string;\n reserveSourceRows?: boolean;\n routeMessage?: string;\n routeStatus?: \"loading\" | \"insufficient\";\n showAutoBadge?: boolean;\n toToken?: SwapTokenOption;\n totalBalance: string;\n usdValue: string;\n}\n\nconst uiFont = '\"Geist\", system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\n\nconst formatToken = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst formatUsd = (value: unknown) => {\n const amount = parseDecimal(value) ?? new Decimal(0);\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n return `$${amount.toDecimalPlaces(2).toFixed()}`;\n};\n\nconst MAX_AMOUNT_DISPLAY_DECIMALS = 8;\nconst getTokenInputDecimals = (token?: Pick) => {\n const decimals = Number(token?.decimals);\n return Number.isFinite(decimals) && decimals >= 0 ? Math.floor(decimals) : 18;\n};\n\nconst formatAmountInputDisplay = (value: string) => {\n if (!value) return \"\";\n try {\n return new Decimal(value)\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n } catch {\n return value;\n }\n};\n\nconst sanitizeAmountInput = (raw: string, maxDecimals: number) => {\n let next = raw.replaceAll(/[^0-9.]/g, \"\");\n const parts = next.split(\".\");\n if (parts.length > 2) next = parts[0] + \".\" + parts.slice(1).join(\"\");\n const [integerPart, decimalPart] = next.split(\".\");\n if (decimalPart !== undefined) {\n next = `${integerPart}.${decimalPart.slice(0, Math.max(0, maxDecimals))}`;\n }\n if (next === \".\") next = \"0.\";\n return next;\n};\n\nfunction TokenLogo({\n src,\n label,\n size = 30,\n fontSize = 12,\n style,\n}: {\n src?: string;\n label?: string;\n size?: number;\n fontSize?: number;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n React.useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction SourceLogoPair({ token }: { token: SwapTokenOption }) {\n return (\n
\n \n {token.chainLogo && (\n \n )}\n
\n );\n}\n\nfunction ExactOutPercentButtons({\n visible,\n onSelect,\n selectedPercent,\n}: {\n visible: boolean;\n onSelect: (pct: number) => void;\n selectedPercent: number | null;\n}) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [focusedPercent, setFocusedPercent] = useState(null);\n\n React.useEffect(() => {\n if (!visible) setFocusedPercent(null);\n }, [visible]);\n\n return (\n \n {[25, 50, 75, 100].map((pct) => {\n const isMax = pct === 100;\n const isFocused = focusedPercent === pct;\n return (\n {\n e.stopPropagation();\n onSelect(pct);\n }}\n onBlur={() => setFocusedPercent(null)}\n onFocus={() => setFocusedPercent(pct)}\n style={{\n alignItems: \"center\",\n backgroundColor: isFocused ? \"var(--nexus-widget-primary-soft, #E8F0FF)\" : \"var(--nexus-widget-surface-raised, #F4F4F3)\",\n border: \"none\",\n borderRadius: \"8px\",\n boxSizing: \"border-box\",\n color: isFocused ? brand : \"var(--nexus-widget-text, #363635)\",\n cursor: \"pointer\",\n display: \"flex\",\n flex: \"1 1 0%\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"12px\",\n fontWeight: 500,\n justifyContent: \"center\",\n lineHeight: \"20px\",\n minWidth: 0,\n paddingBlock: \"5px\",\n paddingInline: \"10px\",\n }}\n type=\"button\"\n >\n {isMax ? \"MAX\" : `${pct}%`}\n \n );\n })}\n \n );\n}\n\nfunction SkeletonRow() {\n return (\n \n \n \n \n );\n}\n\nfunction PayWithSources({\n fromTokens,\n onOpenSourcePicker,\n routeStatus,\n routeMessage,\n}: {\n fromTokens: SwapTokenOption[];\n onOpenSourcePicker: () => void;\n routeStatus?: \"loading\" | \"insufficient\";\n routeMessage?: string;\n}) {\n const scrollRef = useRef(null);\n const isRouteLoading = routeStatus === \"loading\";\n const shouldShowSourceSummary = !isRouteLoading && fromTokens.length > 0;\n const shouldScroll = shouldShowSourceSummary && fromTokens.length > 3;\n const autoBadge = (\n \n AUTO\n \n );\n\n return (\n \n \n \n \n Pay With\n {shouldShowSourceSummary ? ` · ${fromTokens.length} assets` : \"\"}\n \n {autoBadge}\n \n {shouldShowSourceSummary && (\n \n Edit tokens\n \n )}\n \n\n {isRouteLoading ? (\n <>\n \n \n \n Calculating best route...\n \n \n ) : shouldShowSourceSummary ? (\n
\n \n {fromTokens.map((token, index) => (\n \n \n \n \n \n {token.symbol}\n \n \n {token.isUnified\n ? \"Unified balance\"\n : `on ${token.chainName || \"Unknown chain\"}`}\n \n
\n \n \n \n {formatToken(token.userAmount || token.balance)}{\" \"}\n {token.symbol}\n \n \n {formatUsd(token.userAmountUsd || token.balanceInFiat)}\n \n \n \n ))}\n \n {shouldScroll && (\n \n scrollRef.current?.scrollBy({ behavior: \"smooth\", top: 64 })\n }\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${border}`,\n borderRadius: \"999px\",\n bottom: \"4px\",\n boxShadow: \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n cursor: \"pointer\",\n display: \"flex\",\n height: \"22px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"22px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n ) : (\n \n Sources will be auto selected\n \n )}\n\n {routeStatus === \"insufficient\" && routeMessage && (\n \n \n {routeMessage}\n \n )}\n \n );\n}\n\nfunction BalanceSkeleton({\n height = \"16px\",\n width = \"72px\",\n}: {\n height?: string;\n width?: string;\n}) {\n return (\n \n );\n}\n\nexport function SendIdleForm({\n amount,\n onAmountChange,\n toToken,\n fromTokens,\n totalBalance,\n usdValue,\n onOpenAssetPicker,\n onOpenSourcePicker,\n onOpenRecipientPicker,\n recipientAddress,\n onSetPercent,\n routeStatus,\n routeMessage,\n isAmountReadOnly = false,\n isAssetPickerDisabled = false,\n isBalanceLoading = false,\n isCalculatingMax,\n calculatingPercent,\n isQuoteRefreshing,\n isRecipientLocked = false,\n hideDestinationTokenDropdownIcon = false,\n showAutoBadge = true,\n isSourcePickerDisabled = false,\n reserveSourceRows = false,\n}: SendIdleFormProps) {\n const [selectedPercent, setSelectedPercent] = useState(null);\n const [pendingPercent, setPendingPercent] = useState(null);\n const [isAmountFocused, setIsAmountFocused] = useState(false);\n\n React.useEffect(() => {\n if (!isCalculatingMax) setPendingPercent(null);\n }, [isCalculatingMax]);\n\n React.useEffect(() => {\n setSelectedPercent(null);\n }, [toToken?.contractAddress, toToken?.chainId]);\n\n const handlePercentSelect = (pct: number) => {\n setSelectedPercent(pct);\n setPendingPercent(pct);\n onSetPercent(pct);\n };\n\n const handleInput = (e: React.ChangeEvent) => {\n if (isAmountReadOnly) return;\n setSelectedPercent(null);\n onAmountChange(\n sanitizeAmountInput(e.target.value, getTokenInputDecimals(toToken)),\n );\n };\n const amountDisplayValue = isAmountFocused\n ? amount\n : formatAmountInputDisplay(amount);\n const activePendingPercent =\n calculatingPercent ?? (isCalculatingMax ? pendingPercent : null);\n const isMaxCalculating = Boolean(\n isCalculatingMax && activePendingPercent === 100,\n );\n\n const destinationBalanceLabel =\n formatSelectedTokenBalanceLabel(toToken) ||\n `0 ${toToken?.symbol || \"\"}`.trim();\n\n return (\n \n \n \n \n Recipient\n \n \n \n {recipientAddress\n ? `${recipientAddress.slice(0, 6)}…${recipientAddress.slice(-4)}`\n : \"Select recipient\"}\n \n \n \n {isRecipientLocked ? \"Locked\" : \"Edit\"}\n \n \n \n \n \n\n \n \n \n Amount\n \n
\n \n Total Balance:\n \n \n {isBalanceLoading ? (\n \n ) : (\n `$${totalBalance}`\n )}\n \n
\n \n\n
\n \n {isMaxCalculating ? (\n \n ) : (\n setIsAmountFocused(false)}\n onChange={handleInput}\n onFocus={() => setIsAmountFocused(true)}\n placeholder=\"0\"\n style={{\n background: \"transparent\",\n border: \"none\",\n boxSizing: \"border-box\",\n color: amount ? primary : \"var(--nexus-widget-text-tertiary, #C8C8C6)\",\n cursor: isAmountReadOnly ? \"default\" : \"text\",\n flex: \"1 1 0%\",\n fontFamily:\n '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"36px\",\n fontWeight: 500,\n lineHeight: \"44px\",\n minWidth: 0,\n outline: \"none\",\n padding: 0,\n }}\n readOnly={isAmountReadOnly}\n type=\"text\"\n value={amountDisplayValue}\n />\n )}\n {isCalculatingMax && !isMaxCalculating && (\n \n )}\n\n \n {toToken ? (\n \n \n {toToken.chainLogo && (\n \n )}\n
\n ) : (\n \n )}\n \n {toToken ? toToken.symbol : \"Assets\"}\n \n {!hideDestinationTokenDropdownIcon && (\n \n )}\n \n \n\n \n \n \n ≈ ${usdValue || \"0\"}\n \n \n\n \n {toToken && (\n <>\n \n Balance:\n \n \n {isBalanceLoading ? (\n \n ) : (\n destinationBalanceLabel\n )}\n \n \n )}\n \n \n\n \n \n \n\n \n \n );\n}\n", "type": "registry:component", "target": "components/nexus/components/send-idle-form.tsx" }, @@ -80,25 +98,25 @@ }, { "path": "registry/avail-widgets/nexus-widget/components/swap-asset-selector.tsx", - "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\n\"use client\";\nimport type { SupportedChainsAndTokensResult } from \"@avail-project/nexus-core\";\nimport { formatTokenBalance } from \"@avail-project/nexus-core/utils\";\nimport Decimal from \"decimal.js\";\nimport {\n Check,\n ChevronDown,\n ChevronUp,\n Globe,\n Info,\n Loader2,\n Minus,\n Search,\n X,\n} from \"lucide-react\";\nimport React, {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { parseAmount as parseTokenAmount } from \"../utils/amount\";\nimport { useNexusWidgetThemeStyle } from \"../theme-context\";\nimport {\n CHAIN_METADATA,\n getSdkSwapSupportedChainIds,\n getShortChainName,\n isSwapSupportedBySdkChainList,\n} from \"../../common/utils/constant\";\nimport type { UserAsset } from \"../../nexus/NexusProvider\";\n\nconst tabularNums: React.CSSProperties = {\n fontFeatureSettings: '\"tnum\"',\n fontVariantNumeric: \"tabular-nums\",\n};\n\nconst brand = \"var(--foreground-brand)\";\n\nexport interface SwapTokenOption {\n /** Decimal amount without a token symbol; labels are formatted at render time. */\n balance: string;\n balanceInFiat: string;\n chainId?: number;\n chainLogo?: string;\n chainName?: string;\n contractAddress: string;\n decimals: number;\n isUnified?: boolean;\n logo?: string;\n name: string;\n priceUSD?: number | string;\n sourceTokens?: SwapTokenOption[];\n symbol: string;\n unifiedSymbol?: \"USDC\" | \"USDT\" | \"ETH\";\n userAmount?: string;\n userAmountMode?: \"token\" | \"usd\";\n userAmountUsd?: string;\n}\n\ninterface SwapAssetSelectorProps {\n allowSelectedTokenRemoval?: boolean;\n allowUnified?: boolean;\n autoSelectFilterTabs?: boolean;\n editingAssetIndex?: number | null;\n filterTabBehavior?: FilterTabBehavior;\n hideCustomTab?: boolean;\n initialFilterTab?: FilterTab;\n isMulti?: boolean;\n lockedTokens?: SwapTokenOption[];\n onBack: () => void;\n onClearSelection?: () => void;\n onDone?: (tokens?: SwapTokenOption[]) => void;\n onFilterTabSelect?: (tab: FilterTab, scopedTokens?: SwapTokenOption[]) => void;\n onSelect: (token: SwapTokenOption) => void;\n onSelectionChange?: (tokens: SwapTokenOption[], tab?: FilterTab) => void;\n onToggle?: (token: SwapTokenOption) => void;\n preserveSelectedBelowMinimum?: boolean;\n requiredUsd?: string;\n selectedTokens?: SwapTokenOption[];\n showBelowMinimumInline?: boolean;\n staticOptions?: SwapTokenOption[];\n swapBalance: UserAsset[] | null;\n swapSupportedChains?: SupportedChainsAndTokensResult | null;\n title: string;\n}\n\nexport function deriveTokenOptions(\n swapBalance: UserAsset[],\n swapSupportedChains?: SupportedChainsAndTokensResult | null,\n): SwapTokenOption[] {\n const tokens: SwapTokenOption[] = [];\n for (const asset of swapBalance) {\n for (const bd of asset.breakdown ?? []) {\n if (!isSwapSupportedBySdkChainList(bd.chain?.id, swapSupportedChains)) {\n continue;\n }\n if (Number.parseFloat(bd.balance ?? \"0\") <= 0) continue;\n const chainMeta = bd.chain?.id ? CHAIN_METADATA[bd.chain.id] : undefined;\n tokens.push({\n contractAddress: bd.contractAddress,\n symbol: bd.symbol ?? asset.symbol,\n name: bd.symbol ?? asset.symbol,\n logo: asset.logo ?? \"\",\n decimals: bd.decimals ?? asset.decimals ?? 18,\n balance: bd.balance,\n balanceInFiat:\n bd.balanceInFiat != null\n ? `$${Number(bd.balanceInFiat).toFixed(2)}`\n : \"$0.00\",\n chainId: bd.chain?.id,\n chainName: getShortChainName(\n bd.chain?.id,\n chainMeta?.name ?? bd.chain?.name,\n ),\n chainLogo: chainMeta?.logo ?? bd.chain?.logo,\n });\n }\n }\n const seen = new Map();\n for (const t of tokens) {\n seen.set(`${t.contractAddress.toLowerCase()}-${t.chainId}`, t);\n }\n return Array.from(seen.values());\n}\n\n/* ── Radio dot (circular) ── */\nexport const RadioDot = ({ selected }: { selected: boolean }) => (\n \n {selected && (\n \n )}\n \n);\n\nconst SelectionControl = ({\n selected,\n indeterminate = false,\n multi,\n}: {\n selected: boolean;\n indeterminate?: boolean;\n multi: boolean;\n}) => {\n if (!multi) return ;\n\n const isActive = selected || indeterminate;\n\n return (\n \n {selected && (\n \n )}\n {!selected && indeterminate && (\n \n )}\n \n );\n};\n\nfunction TokenLogo({\n src,\n label,\n size,\n fontSize,\n style,\n fallbackBackground = brand,\n fallbackColor = \"var(--nexus-widget-surface, #FFFFFE)\",\n}: {\n src?: string;\n label?: string;\n size: number;\n fontSize: number;\n style?: React.CSSProperties;\n fallbackBackground?: string;\n fallbackColor?: string;\n}) {\n const normalizedSrc = src?.trim();\n const [failed, setFailed] = useState(!normalizedSrc);\n\n useEffect(() => {\n setFailed(!normalizedSrc);\n }, [normalizedSrc]);\n\n if (!failed && normalizedSrc) {\n return (\n setFailed(true)}\n src={normalizedSrc}\n style={{\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").slice(0, 2).toUpperCase()}\n \n );\n}\n\nconst getChainLogo = (\n token?: Pick | null,\n) => {\n if (!token) return undefined;\n return token.chainId\n ? (CHAIN_METADATA[token.chainId]?.logo ?? token.chainLogo)\n : token.chainLogo;\n};\n\n/* ── Chain logo cluster ── */\nconst ChainLogos = ({ tokens }: { tokens: SwapTokenOption[] }) => {\n const themeStyle = useNexusWidgetThemeStyle();\n const clusterRef = useRef(null);\n const closeTimerRef = useRef | null>(null);\n const [showTooltip, setShowTooltip] = useState(false);\n const [tooltipRect, setTooltipRect] = useState(null);\n const uniqueChains = useMemo(() => {\n const seen = new Set();\n const out: {\n id: number;\n logo?: string;\n name?: string;\n balance?: string;\n balanceInFiat?: string;\n balanceValue: number;\n fiatValue: number;\n }[] = [];\n for (const t of tokens) {\n if (t.chainId && !seen.has(t.chainId)) {\n const balanceValue = parseTokenAmount(t.balance)?.toNumber() ?? 0;\n seen.add(t.chainId);\n out.push({\n id: t.chainId,\n logo: getChainLogo(t),\n name: getShortChainName(t.chainId, t.chainName),\n balance: t.balance,\n balanceInFiat: t.balanceInFiat,\n balanceValue:\n Number.isNaN(balanceValue) || !Number.isFinite(balanceValue)\n ? 0\n : balanceValue,\n fiatValue: getTokenFiatValue(t),\n });\n }\n }\n return out.sort((a, b) => {\n if (a.fiatValue !== b.fiatValue) return b.fiatValue - a.fiatValue;\n if (a.balanceValue !== b.balanceValue) {\n return b.balanceValue - a.balanceValue;\n }\n return (a.name ?? \"\").localeCompare(b.name ?? \"\");\n });\n }, [tokens]);\n\n const maxShow = 3;\n const shown = uniqueChains.slice(0, maxShow);\n const openTooltip = () => {\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n setTooltipRect(clusterRef.current?.getBoundingClientRect() ?? null);\n setShowTooltip(true);\n };\n const closeTooltip = () => {\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n closeTimerRef.current = setTimeout(() => {\n setShowTooltip(false);\n closeTimerRef.current = null;\n }, 120);\n };\n useEffect(() => {\n return () => {\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n };\n }, []);\n const showTooltipAbove = tooltipRect ? tooltipRect.top > 240 : true;\n const tooltip =\n showTooltip && uniqueChains.length > 1 && tooltipRect\n ? createPortal(\n \n \n UNIFIED · {uniqueChains.length} CHAINS\n \n {tokens\n .reduce((sum, token) => sum + getTokenFiatValue(token), 0)\n .toLocaleString(undefined, {\n currency: \"USD\",\n maximumFractionDigits: 2,\n style: \"currency\",\n })}\n \n \n {uniqueChains.map((chain) => (\n \n \n \n \n {chain.name || \"Unknown chain\"}\n \n \n \n {chain.balance\n ? formatTokenAmountDisplay(chain.balance)\n : chain.balanceInFiat || \"0\"}\n \n \n ))}\n ,\n document.body,\n )\n : null;\n\n return (\n \n {tooltip}\n {shown.map((c) => (\n \n ))}\n \n {uniqueChains.length} chain{uniqueChains.length !== 1 ? \"s\" : \"\"}\n \n \n );\n};\n\n/* ── Filter tabs ── */\ntype FilterTab = \"all\" | \"native\" | \"stables\" | \"custom\";\ntype FilterTabBehavior = \"select-all\" | \"source-pool\";\nconst FILTER_TABS: { key: FilterTab; label: string }[] = [\n { key: \"all\", label: \"All\" },\n { key: \"native\", label: \"Native\" },\n { key: \"stables\", label: \"Stables\" },\n { key: \"custom\", label: \"Manual\" },\n];\nconst STABLE_SYMBOLS = new Set([\n \"AUSD\",\n \"BDO\",\n \"BRZ\",\n \"BTCUSD\",\n \"BUSD\",\n \"bnbUSD\",\n \"crvUSD\",\n \"CUSD\",\n \"DAI\",\n \"DAI.e\",\n \"dEURO\",\n \"DUSD\",\n \"EURA\",\n \"EURC\",\n \"EURCV\",\n \"EURe\",\n \"EURS\",\n \"EURT\",\n \"eUSD\",\n \"frxUSD\",\n \"GHO\",\n \"GUSD\",\n \"JUST\",\n \"jEUR\",\n \"JUSD\",\n \"LUSD\",\n \"rUSD\",\n \"RLUSD\",\n \"sUSD\",\n \"svJUSD\",\n \"TUSD\",\n \"USDC\",\n \"USDC.e\",\n \"USDS\",\n \"USDT\",\n \"USDT0\",\n \"USDT.e\",\n \"ctUSD\",\n \"PYUSD\",\n \"USDe\",\n \"xDAI\",\n \"USD0\",\n \"USDM\",\n]);\nconst normalizeTokenGroupSymbol = (symbol: string) =>\n symbol\n .trim()\n .toUpperCase()\n .replaceAll(\"₮\", \"T\")\n .replaceAll(/[^A-Z0-9]/g, \"\");\nconst STABLE_SYMBOL_KEYS = new Set(\n Array.from(STABLE_SYMBOLS, normalizeTokenGroupSymbol),\n);\n\nconst isStableToken = (token: SwapTokenOption) =>\n STABLE_SYMBOL_KEYS.has(normalizeTokenGroupSymbol(token.symbol));\n\nfunction isNativeToken(t: SwapTokenOption) {\n if (isNativeLikeAddress(t.contractAddress)) return true;\n\n const sym = t.symbol.toUpperCase();\n const chain = (t.chainName || \"\").toLowerCase();\n\n if (sym === \"ETH\")\n return (\n !chain.includes(\"bnb\") &&\n !chain.includes(\"bsc\") &&\n !chain.includes(\"polygon\") &&\n !chain.includes(\"monad\") &&\n !chain.includes(\"hyperevm\")\n );\n if (sym === \"POL\" || sym === \"MATIC\") return chain.includes(\"polygon\");\n if (sym === \"HYPE\") return chain.includes(\"hyperevm\");\n if (sym === \"MON\") return chain.includes(\"monad\");\n if (sym === \"BNB\") return chain.includes(\"bnb\") || chain.includes(\"bsc\");\n if (sym === \"AVAX\") return chain.includes(\"avalanche\");\n if (sym === \"FTM\") return chain.includes(\"fantom\");\n if (sym === \"CELO\") return chain.includes(\"celo\");\n if (sym === \"SUI\") return chain.includes(\"sui\");\n if (sym === \"APT\") return chain.includes(\"aptos\");\n if (sym === \"SOL\") return chain.includes(\"solana\");\n return false;\n}\n\nconst MIN_FIAT_THRESHOLD = 1;\nconst CHAIN_SELECTOR_CLOSE_MS = 220;\nconst MODAL_HEIGHT_TRANSITION_MS = 260;\nconst modalHeightTransitionStyle = {\n interpolateSize: \"allow-keywords\",\n} as React.CSSProperties;\nconst modalHeightTransition = `height ${MODAL_HEIGHT_TRANSITION_MS}ms ease, max-height ${MODAL_HEIGHT_TRANSITION_MS}ms ease`;\nexport const SWAP_CHAIN_DISPLAY_ORDER = [\n 1, // Ethereum\n 42161, // Arbitrum\n 8453, // Base\n 137, // Polygon\n 10, // OP\n 999, // HyperEVM\n 56, // BSC\n // 43114, // Avalanche\n 143, // Monad\n 4326, // MegaETH\n 4114, // Citrea\n 8217, // Kaia\n 534352, // Scroll\n] as const;\nconst SWAP_CHAIN_DISPLAY_ORDER_RANK = new Map(\n SWAP_CHAIN_DISPLAY_ORDER.map((chainId, index) => [chainId, index]),\n);\nexport const SWAP_CHAIN_DISPLAY_ORDER_SET = new Set(\n SWAP_CHAIN_DISPLAY_ORDER,\n);\nexport const sortChainIdsBySwapDisplayOrder = (chainIds: number[]) =>\n [...chainIds].sort((a, b) => {\n const aRank =\n SWAP_CHAIN_DISPLAY_ORDER_RANK.get(a) ?? Number.MAX_SAFE_INTEGER;\n const bRank =\n SWAP_CHAIN_DISPLAY_ORDER_RANK.get(b) ?? Number.MAX_SAFE_INTEGER;\n if (aRank !== bRank) return aRank - bRank;\n\n const aName = CHAIN_METADATA[a]?.name ?? String(a);\n const bName = CHAIN_METADATA[b]?.name ?? String(b);\n return aName.localeCompare(bName);\n });\nexport const compareChainsBySwapDisplayOrder = <\n T extends { chainId?: number; chainName?: string },\n>(\n a: T,\n b: T,\n) => {\n const aRank =\n SWAP_CHAIN_DISPLAY_ORDER_RANK.get(a.chainId ?? -1) ??\n Number.MAX_SAFE_INTEGER;\n const bRank =\n SWAP_CHAIN_DISPLAY_ORDER_RANK.get(b.chainId ?? -1) ??\n Number.MAX_SAFE_INTEGER;\n if (aRank !== bRank) return aRank - bRank;\n return (a.chainName ?? \"\").localeCompare(b.chainName ?? \"\");\n};\nconst UNIFIED_MAINNET_CHAIN_IDS = new Set([\n 1, 10, 56, 137, 143, 999, 4114, 8217, 8453, 42161, 43114, 534352, 4326,\n]);\nconst UNIFIED_USDC_SYMBOL_KEYS = new Set([\"USDC\", \"USDCE\", \"USDM\"]);\nconst UNIFIED_USDT_SYMBOL_KEYS = new Set([\"USDT\", \"USDT0\", \"USDTE\"]);\n\nconst getTokenFiatValue = (token: Pick) => {\n const parsed = parseTokenAmount(token.balanceInFiat)?.toNumber() ?? 0;\n return isNaN(parsed) || !isFinite(parsed) ? 0 : parsed;\n};\n\nconst formatBalanceWithSymbol = (\n token: Pick,\n) => {\n const symbol = token.symbol?.trim() || \"\";\n const formatted = formatTokenAmountDisplay(token.balance);\n return symbol ? `${formatted} ${symbol}` : formatted;\n};\n\nconst compareTokensByUsdBalance = (a: SwapTokenOption, b: SwapTokenOption) => {\n const fiatDelta = getTokenFiatValue(b) - getTokenFiatValue(a);\n if (fiatDelta !== 0) return fiatDelta;\n\n const aBalance = parseTokenAmount(a.balance) ?? new Decimal(0);\n const bBalance = parseTokenAmount(b.balance) ?? new Decimal(0);\n const balanceDelta = bBalance.cmp(aBalance);\n if (balanceDelta !== 0) return balanceDelta;\n\n const chainDelta = compareChainsBySwapDisplayOrder(a, b);\n if (chainDelta !== 0) return chainDelta;\n\n return `${a.symbol} ${a.chainName}`.localeCompare(\n `${b.symbol} ${b.chainName}`,\n );\n};\n\nconst sortTokensByUsdBalance = (tokens: SwapTokenOption[]) =>\n [...tokens].sort(compareTokensByUsdBalance);\n\nexport const formatTokenAmountDisplay = (value: unknown) => {\n const amount = parseTokenAmount(value) ?? new Decimal(0);\n const abs = amount.abs();\n\n if (amount.isZero()) return \"0\";\n\n const compactUnits = [\n { suffix: \"T\", value: new Decimal(1_000_000_000_000) },\n { suffix: \"B\", value: new Decimal(1_000_000_000) },\n { suffix: \"M\", value: new Decimal(1_000_000) },\n ];\n\n for (const unit of compactUnits) {\n if (abs.gte(unit.value)) {\n return `${amount\n .div(unit.value)\n .toDecimalPlaces(4, Decimal.ROUND_DOWN)\n .toFixed()}${unit.suffix}`;\n }\n }\n\n const minDisplay = new Decimal(\"0.00000001\");\n if (amount.gt(0) && amount.lt(minDisplay)) {\n return `>${minDisplay.toFixed()}`;\n }\n\n return amount.toDecimalPlaces(8, Decimal.ROUND_DOWN).toFixed();\n};\n\nconst addThousandsSeparators = (value: string) => {\n const [integerPart, decimalPart] = value.split(\".\");\n const withSeparators = integerPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n return decimalPart === undefined\n ? withSeparators\n : `${withSeparators}.${decimalPart}`;\n};\n\nexport const formatUsdBalanceLabel = (value: unknown) => {\n const amount = parseTokenAmount(value) ?? new Decimal(0);\n const abs = amount.abs();\n\n if (amount.isZero()) return \"$0.00\";\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n\n const compactUnits = [\n { suffix: \"T\", value: new Decimal(1_000_000_000_000) },\n { suffix: \"B\", value: new Decimal(1_000_000_000) },\n { suffix: \"M\", value: new Decimal(1_000_000) },\n ];\n\n for (const unit of compactUnits) {\n if (abs.gte(unit.value)) {\n return `$${amount\n .div(unit.value)\n .toDecimalPlaces(4, Decimal.ROUND_DOWN)\n .toFixed()}${unit.suffix}`;\n }\n }\n\n return `$${addThousandsSeparators(amount.toDecimalPlaces(2).toFixed(2))}`;\n};\n\nexport const formatSelectedTokenBalanceLabel = (\n token?: Pick,\n) => {\n if (!token) return \"\";\n const symbol = token.symbol || \"\";\n const formatted = formatTokenAmountDisplay(token.balance);\n return symbol ? `${formatted} ${symbol}` : formatted;\n};\n\nconst getSearchTerms = (query: string) =>\n query.toLowerCase().trim().split(/\\s+/).filter(Boolean);\n\nconst includesTerm = (value: string | undefined, term: string) =>\n (value ?? \"\").toLowerCase().includes(term);\n\nconst startsWithTerm = (value: string | undefined, term: string) =>\n (value ?? \"\").toLowerCase().startsWith(term);\n\nconst equalsTerm = (value: string | undefined, term: string) =>\n (value ?? \"\").toLowerCase() === term;\n\nexport const getTokenSearchRank = (\n token: Pick<\n SwapTokenOption,\n \"symbol\" | \"name\" | \"chainName\" | \"contractAddress\"\n >,\n query: string,\n) => {\n const terms = getSearchTerms(query);\n if (terms.length === 0) return null;\n\n let matchedTerms = 0;\n let symbolExactTerms = 0;\n let symbolPrefixTerms = 0;\n let symbolIncludeTerms = 0;\n let namePrefixTerms = 0;\n let tokenExactTerms = 0;\n let tokenPrefixTerms = 0;\n let tokenIncludeTerms = 0;\n let chainExactTerms = 0;\n let chainPrefixTerms = 0;\n let chainIncludeTerms = 0;\n let addressTerms = 0;\n\n for (const term of terms) {\n const symbolExact = equalsTerm(token.symbol, term);\n const symbolPrefix = symbolExact || startsWithTerm(token.symbol, term);\n const symbolInclude = symbolPrefix || includesTerm(token.symbol, term);\n const nameExact = equalsTerm(token.name, term);\n const namePrefix = nameExact || startsWithTerm(token.name, term);\n const nameInclude = namePrefix || includesTerm(token.name, term);\n const tokenExact = symbolExact || nameExact;\n const tokenPrefix = tokenExact || symbolPrefix || namePrefix;\n const tokenInclude = tokenPrefix || symbolInclude || nameInclude;\n const chainExact = equalsTerm(token.chainName, term);\n const chainPrefix = chainExact || startsWithTerm(token.chainName, term);\n const chainInclude = chainPrefix || includesTerm(token.chainName, term);\n const addressMatch = includesTerm(token.contractAddress, term);\n\n if (tokenInclude || chainInclude || addressMatch) matchedTerms += 1;\n if (symbolExact) symbolExactTerms += 1;\n if (symbolPrefix) symbolPrefixTerms += 1;\n if (symbolInclude) symbolIncludeTerms += 1;\n if (namePrefix) namePrefixTerms += 1;\n if (tokenExact) tokenExactTerms += 1;\n if (tokenPrefix) tokenPrefixTerms += 1;\n if (tokenInclude) tokenIncludeTerms += 1;\n if (chainExact) chainExactTerms += 1;\n if (chainPrefix) chainPrefixTerms += 1;\n if (chainInclude) chainIncludeTerms += 1;\n if (addressMatch) addressTerms += 1;\n }\n\n const allTermsMatched = matchedTerms === terms.length;\n if (!allTermsMatched) return null;\n\n if (\n terms.length > 1 &&\n chainIncludeTerms > 0 &&\n symbolIncludeTerms === 0 &&\n addressTerms === 0 &&\n namePrefixTerms === 0\n ) {\n return null;\n }\n\n const hasTokenMatch = tokenIncludeTerms > 0;\n const hasChainMatch = chainIncludeTerms > 0;\n const isTokenChainMatch = allTermsMatched && hasTokenMatch && hasChainMatch;\n\n let score = 20;\n if (isTokenChainMatch) {\n if (symbolExactTerms > 0 && chainExactTerms > 0) score = 0;\n else if (symbolExactTerms > 0 && chainPrefixTerms > 0) score = 1;\n else if (symbolExactTerms > 0 && chainIncludeTerms > 0) score = 2;\n else if (symbolPrefixTerms > 0 && chainIncludeTerms > 0) score = 3;\n else if (symbolIncludeTerms > 0 && chainIncludeTerms > 0) score = 4;\n else if (namePrefixTerms > 0 && chainIncludeTerms > 0) score = 5;\n else score = 6;\n } else if (symbolExactTerms > 0) score = 7;\n else if (symbolPrefixTerms > 0) score = 8;\n else if (symbolIncludeTerms > 0) score = 9;\n else if (tokenExactTerms > 0) score = 10;\n else if (tokenPrefixTerms > 0) score = 11;\n else if (tokenIncludeTerms > 0) score = 12;\n else if (chainExactTerms > 0) score = 13;\n else if (chainPrefixTerms > 0) score = 14;\n else if (chainIncludeTerms > 0) score = 15;\n else if (addressTerms > 0) score = 16;\n\n return {\n allTermsMatched,\n isTokenChainMatch,\n matchedTerms,\n score,\n tokenExactTerms,\n tokenIncludeTerms,\n };\n};\n\nconst isPrioritySearchMatch = (token: SwapTokenOption, query: string) => {\n const rank = getTokenSearchRank(token, query);\n return Boolean(\n rank &&\n (rank.isTokenChainMatch ||\n rank.tokenExactTerms > 0 ||\n rank.allTermsMatched),\n );\n};\n\nconst compareTokensBySearch = (\n a: SwapTokenOption,\n b: SwapTokenOption,\n query: string,\n) => {\n const aRank = getTokenSearchRank(a, query);\n const bRank = getTokenSearchRank(b, query);\n const aScore = aRank?.score ?? Number.MAX_SAFE_INTEGER;\n const bScore = bRank?.score ?? Number.MAX_SAFE_INTEGER;\n if (aScore !== bScore) return aScore - bScore;\n\n const aMatched = aRank?.matchedTerms ?? 0;\n const bMatched = bRank?.matchedTerms ?? 0;\n if (aMatched !== bMatched) return bMatched - aMatched;\n\n const aFiat = getTokenFiatValue(a);\n const bFiat = getTokenFiatValue(b);\n if (aFiat !== bFiat) return bFiat - aFiat;\n\n return `${a.symbol} ${a.chainName}`.localeCompare(\n `${b.symbol} ${b.chainName}`,\n );\n};\n\nfunction getUnifiedSymbol(token: Pick) {\n if (token.chainId && !UNIFIED_MAINNET_CHAIN_IDS.has(token.chainId)) {\n return null;\n }\n\n const symbol = normalizeTokenGroupSymbol(token.symbol);\n if (UNIFIED_USDC_SYMBOL_KEYS.has(symbol)) return \"USDC\" as const;\n if (UNIFIED_USDT_SYMBOL_KEYS.has(symbol)) return \"USDT\" as const;\n if (symbol === \"ETH\") return \"ETH\" as const;\n return null;\n}\n\nfunction sameTokenOption(a?: SwapTokenOption, b?: SwapTokenOption) {\n if (!a || !b) return false;\n if (a.isUnified || b.isUnified) {\n return Boolean(\n a.isUnified && b.isUnified && a.unifiedSymbol === b.unifiedSymbol,\n );\n }\n return (\n sameContractAddress(a.contractAddress, b.contractAddress) &&\n a.chainId === b.chainId\n );\n}\n\nfunction isSameTokenList(a: SwapTokenOption[], b: SwapTokenOption[]) {\n if (a.length !== b.length) return false;\n return a.every((tokenA) =>\n b.some((tokenB) => sameTokenOption(tokenA, tokenB)),\n );\n}\n\nfunction dedupeTokenOptions(tokens: SwapTokenOption[]) {\n return tokens.reduce((acc, token) => {\n if (!acc.some((item) => sameTokenOption(item, token))) {\n acc.push(token);\n }\n return acc;\n }, []);\n}\n\nfunction mergeTokenOptions(\n base: SwapTokenOption[],\n additions: SwapTokenOption[],\n) {\n return dedupeTokenOptions([...base, ...additions]);\n}\n\nfunction removeTokenOptions(\n base: SwapTokenOption[],\n removals: SwapTokenOption[],\n) {\n return base.filter(\n (token) => !removals.some((removal) => sameTokenOption(token, removal)),\n );\n}\n\nfunction isNativeLikeAddress(address?: string) {\n const normalized = (address ?? \"\").toLowerCase();\n return (\n normalized === \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\" ||\n normalized === \"0x0000000000000000000000000000000000000000\"\n );\n}\n\nfunction addressTail(address?: string) {\n const normalized = (address ?? \"\").toLowerCase();\n if (!normalized.startsWith(\"0x\")) return normalized;\n return normalized.slice(-40);\n}\n\nfunction sameContractAddress(a?: string, b?: string) {\n const normalizedA = (a ?? \"\").toLowerCase();\n const normalizedB = (b ?? \"\").toLowerCase();\n if (!normalizedA || !normalizedB) return normalizedA === normalizedB;\n if (normalizedA === normalizedB) return true;\n if (isNativeLikeAddress(normalizedA) && isNativeLikeAddress(normalizedB)) {\n return true;\n }\n return addressTail(normalizedA) === addressTail(normalizedB);\n}\n\nexport function SwapAssetSelector({\n title,\n swapBalance,\n swapSupportedChains,\n staticOptions,\n onSelect,\n onBack,\n isMulti,\n selectedTokens = [],\n editingAssetIndex = null,\n onToggle,\n onClearSelection,\n onDone,\n allowUnified = false,\n preserveSelectedBelowMinimum = false,\n showBelowMinimumInline = false,\n allowSelectedTokenRemoval = false,\n hideCustomTab = false,\n autoSelectFilterTabs = false,\n initialFilterTab = \"all\",\n filterTabBehavior = \"select-all\",\n onFilterTabSelect,\n lockedTokens = [],\n onSelectionChange,\n requiredUsd,\n}: SwapAssetSelectorProps) {\n const sdkSwapSupportedChainIds = useMemo(\n () => getSdkSwapSupportedChainIds(swapSupportedChains),\n [swapSupportedChains],\n );\n const selectorRef = useRef(null);\n const listRef = useRef(null);\n const chainCloseTimerRef = useRef | null>(null);\n const [portalRoot, setPortalRoot] = useState(null);\n const [query, setQuery] = useState(\"\");\n const normalizedInitialFilterTab =\n hideCustomTab && initialFilterTab === \"custom\" ? \"all\" : initialFilterTab;\n const [activeTab, setActiveTab] = useState(\n normalizedInitialFilterTab,\n );\n const [showBelowMin, setShowBelowMin] = useState(false);\n const [isSearchFocused, setIsSearchFocused] = useState(false);\n const [showChainSelector, setShowChainSelector] = useState(false);\n const [isChainSelectorClosing, setIsChainSelectorClosing] = useState(false);\n const [chainQuery, setChainQuery] = useState(\"\");\n const [selectedChainFilter, setSelectedChainFilter] = useState(\n null,\n );\n const [isChainSearchFocused, setIsChainSearchFocused] = useState(false);\n const stableListHeightRef = useRef(0);\n const pendingSelectionScrollTopRef = useRef(null);\n const skipNextSelectionScrollResetRef = useRef(false);\n const [stableListHeight, setStableListHeight] = useState(null);\n const lockedSelectedTokens = useMemo(\n () => dedupeTokenOptions(lockedTokens),\n [lockedTokens],\n );\n const isLockedToken = useCallback(\n (token: SwapTokenOption) =>\n lockedSelectedTokens.some((locked) => sameTokenOption(locked, token)),\n [lockedSelectedTokens],\n );\n const [draftSelectedTokens, setDraftSelectedTokens] = useState<\n SwapTokenOption[]\n >(() => mergeTokenOptions(selectedTokens, lockedSelectedTokens));\n useEffect(() => {\n if (!isMulti) return;\n setDraftSelectedTokens(\n mergeTokenOptions(selectedTokens, lockedSelectedTokens),\n );\n }, [isMulti, lockedSelectedTokens, selectedTokens]);\n const activeSelectedTokens = isMulti ? draftSelectedTokens : selectedTokens;\n const emitSelectionChange = useCallback(\n (tokens: SwapTokenOption[], tab: FilterTab = activeTab) => {\n const next = mergeTokenOptions(tokens, lockedSelectedTokens);\n if (isMulti) {\n setDraftSelectedTokens(next);\n }\n onSelectionChange?.(next, tab);\n },\n [activeTab, isMulti, lockedSelectedTokens, onSelectionChange],\n );\n const visibleFilterTabs = useMemo(\n () =>\n hideCustomTab\n ? FILTER_TABS.filter((tab) => tab.key !== \"custom\")\n : FILTER_TABS,\n [hideCustomTab],\n );\n\n useEffect(() => {\n if (hideCustomTab && activeTab === \"custom\") {\n setActiveTab(\"all\");\n }\n }, [activeTab, hideCustomTab]);\n\n useEffect(() => {\n setActiveTab((current) =>\n current === normalizedInitialFilterTab\n ? current\n : normalizedInitialFilterTab,\n );\n }, [normalizedInitialFilterTab]);\n\n useEffect(() => {\n if (skipNextSelectionScrollResetRef.current) {\n skipNextSelectionScrollResetRef.current = false;\n return;\n }\n if (listRef.current) {\n listRef.current.scrollTop = 0;\n }\n }, [query, activeTab, selectedChainFilter]);\n\n useLayoutEffect(() => {\n const pendingScrollTop = pendingSelectionScrollTopRef.current;\n if (pendingScrollTop === null) return;\n\n if (listRef.current) {\n listRef.current.scrollTop = pendingScrollTop;\n }\n pendingSelectionScrollTopRef.current = null;\n }, [draftSelectedTokens]);\n\n const allTokens = useMemo(() => {\n const isSwapSupportedToken = (token: SwapTokenOption) =>\n isSwapSupportedBySdkChainList(token.chainId, swapSupportedChains);\n\n const baseTokens = staticOptions\n ? staticOptions.filter(isSwapSupportedToken)\n : swapBalance\n ? deriveTokenOptions(swapBalance, swapSupportedChains)\n : [];\n\n if (!preserveSelectedBelowMinimum && lockedSelectedTokens.length === 0) {\n return sortTokensByUsdBalance(baseTokens);\n }\n\n const merged = [...baseTokens];\n const selectedSourceTokens = [\n ...activeSelectedTokens,\n ...lockedSelectedTokens,\n ].flatMap((token) =>\n token.isUnified && token.sourceTokens?.length\n ? token.sourceTokens\n : [token],\n );\n\n for (const selectedToken of selectedSourceTokens) {\n const alreadyPresent = merged.some((token) =>\n sameTokenOption(token, selectedToken),\n );\n if (!alreadyPresent) {\n merged.push(selectedToken);\n }\n }\n\n return sortTokensByUsdBalance(merged.filter(isSwapSupportedToken));\n }, [\n lockedSelectedTokens,\n preserveSelectedBelowMinimum,\n activeSelectedTokens,\n swapBalance,\n swapSupportedChains,\n staticOptions,\n ]);\n\n const getFilterTabTokens = useCallback(\n (tab: FilterTab, chainId = selectedChainFilter) => {\n let result = allTokens;\n if (chainId !== null) {\n result = result.filter(\n (token) => token.chainId === chainId,\n );\n }\n if (tab === \"native\") result = result.filter(isNativeToken);\n else if (tab === \"stables\") {\n result = result.filter(isStableToken);\n }\n\n if (showBelowMinimumInline) {\n return mergeTokenOptions(result, lockedSelectedTokens);\n }\n\n return mergeTokenOptions(\n result.filter(\n (token) => getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD,\n ),\n lockedSelectedTokens,\n );\n },\n [allTokens, lockedSelectedTokens, selectedChainFilter, showBelowMinimumInline],\n );\n\n /* Search + tab + chain filter */\n const filtered = useMemo(() => {\n let result = allTokens;\n if (selectedChainFilter !== null) {\n result = result.filter((t) => t.chainId === selectedChainFilter);\n }\n if (query.trim()) {\n result = result\n .filter((t) => getTokenSearchRank(t, query) !== null)\n .sort((a, b) => compareTokensBySearch(a, b, query));\n }\n if (activeTab === \"native\") result = result.filter(isNativeToken);\n else if (activeTab === \"stables\") result = result.filter(isStableToken);\n else if (activeTab === \"custom\" && !autoSelectFilterTabs)\n result = result.filter((t) => !isNativeToken(t) && !isStableToken(t));\n return result;\n }, [activeTab, allTokens, autoSelectFilterTabs, query, selectedChainFilter]);\n\n const isTokenSelectedForVisibility = useCallback(\n (token: SwapTokenOption) => {\n if (isLockedToken(token)) return true;\n if (!preserveSelectedBelowMinimum) return false;\n\n return activeSelectedTokens.some(\n (selected) =>\n sameTokenOption(selected, token) ||\n Boolean(\n selected.isUnified &&\n selected.sourceTokens?.some((source) =>\n sameTokenOption(source, token),\n ),\n ),\n );\n },\n [activeSelectedTokens, isLockedToken, preserveSelectedBelowMinimum],\n );\n\n const isUnifiedSelectedForVisibility = useCallback(\n (symbol: string) =>\n preserveSelectedBelowMinimum &&\n activeSelectedTokens.some(\n (selected) => selected.isUnified && selected.unifiedSymbol === symbol,\n ),\n [activeSelectedTokens, preserveSelectedBelowMinimum],\n );\n\n /* Split into above/below minimum */\n const { aboveMin, belowMin } = useMemo(() => {\n const above: SwapTokenOption[] = [];\n const below: SwapTokenOption[] = [];\n for (const t of filtered) {\n const fiat = getTokenFiatValue(t);\n if (\n showBelowMinimumInline ||\n fiat >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(t) ||\n isPrioritySearchMatch(t, query)\n )\n above.push(t);\n else below.push(t);\n }\n return { aboveMin: above, belowMin: below };\n }, [filtered, isTokenSelectedForVisibility, query, showBelowMinimumInline]);\n\n /* Group by symbol */\n const groupedFiltered = useMemo(() => {\n const groups: Record = {};\n for (const token of filtered) {\n const unifiedSym = allowUnified ? getUnifiedSymbol(token) : null;\n if (\n !showBelowMinimumInline &&\n unifiedSym &&\n getTokenFiatValue(token) < MIN_FIAT_THRESHOLD &&\n !isTokenSelectedForVisibility(token)\n ) {\n continue;\n }\n const key = unifiedSym ?? `${token.contractAddress}-${token.chainId}`;\n if (!groups[key]) groups[key] = [];\n groups[key].push(token);\n }\n return Object.values(groups)\n .map((group) => {\n const sortedGroup = sortTokensByUsdBalance(group);\n let totalFiatVal = 0;\n let totalBalVal = 0;\n for (const t of sortedGroup) {\n const fiatVal = getTokenFiatValue(t);\n totalFiatVal += isNaN(fiatVal) || !isFinite(fiatVal) ? 0 : fiatVal;\n const balVal = parseTokenAmount(t.balance)?.toNumber() ?? 0;\n totalBalVal += isNaN(balVal) || !isFinite(balVal) ? 0 : balVal;\n }\n const unifiedSym = allowUnified\n ? getUnifiedSymbol(sortedGroup[0])\n : null;\n const symbol = unifiedSym ?? sortedGroup[0].symbol;\n const isStable = [\"USDC\", \"USDT\", \"DAI\", \"USDM\", \"CTUSD\"].includes(\n symbol.toUpperCase(),\n );\n const maxDigits = isStable ? 2 : 6;\n const formattedBal = totalBalVal.toLocaleString(undefined, {\n minimumFractionDigits: 0,\n maximumFractionDigits: maxDigits,\n });\n\n return {\n symbol,\n logo: sortedGroup[0].logo,\n totalFiat: totalFiatVal,\n totalFiatStr: `$${totalFiatVal.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 })}`,\n totalBalStr: `${formattedBal} ${symbol}`,\n totalBalRaw: totalBalVal,\n tokens: sortedGroup,\n isUnifiedCandidate: Boolean(unifiedSym && group.length > 1),\n };\n })\n .filter((group) => {\n const hasSelectedToken = group.tokens.some(\n isTokenSelectedForVisibility,\n );\n const hasSelectedUnified = isUnifiedSelectedForVisibility(group.symbol);\n const hasPrioritySearchMatch = group.tokens.some((token) =>\n isPrioritySearchMatch(token, query),\n );\n if (showBelowMinimumInline) {\n return true;\n }\n if (group.isUnifiedCandidate) {\n return (\n group.totalFiat >= MIN_FIAT_THRESHOLD ||\n hasSelectedToken ||\n hasSelectedUnified ||\n hasPrioritySearchMatch\n );\n }\n return group.tokens.some(\n (token) =>\n getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(token) ||\n isPrioritySearchMatch(token, query),\n );\n })\n .sort((a, b) => {\n if (query.trim()) {\n const aScore = Math.min(\n ...a.tokens.map(\n (token) =>\n getTokenSearchRank(token, query)?.score ??\n Number.MAX_SAFE_INTEGER,\n ),\n );\n const bScore = Math.min(\n ...b.tokens.map(\n (token) =>\n getTokenSearchRank(token, query)?.score ??\n Number.MAX_SAFE_INTEGER,\n ),\n );\n if (aScore !== bScore) return aScore - bScore;\n }\n return b.totalFiat - a.totalFiat;\n });\n }, [\n filtered,\n allowUnified,\n isTokenSelectedForVisibility,\n isUnifiedSelectedForVisibility,\n query,\n ]);\n\n const [expandedGroups, setExpandedGroups] = useState>(new Set());\n\n const toggleGroup = (symbol: string, e: React.MouseEvent) => {\n e.stopPropagation();\n setExpandedGroups((prev) => {\n const next = new Set(prev);\n if (next.has(symbol)) next.delete(symbol);\n else next.add(symbol);\n return next;\n });\n };\n\n const isTokenSelectedInOtherSlot = (token: SwapTokenOption) =>\n !allowSelectedTokenRemoval &&\n activeSelectedTokens.some(\n (st, idx) => idx !== editingAssetIndex && sameTokenOption(st, token),\n );\n\n const isTokenSelectedInCurrentSlot = (token: SwapTokenOption) => {\n if (isMulti) {\n return activeSelectedTokens.some(\n (st) =>\n sameTokenOption(st, token) ||\n Boolean(\n st.isUnified &&\n st.sourceTokens?.some((source) => sameTokenOption(source, token)),\n ),\n );\n }\n if (allowSelectedTokenRemoval) {\n return activeSelectedTokens.some(\n (st) =>\n sameTokenOption(st, token) ||\n Boolean(\n st.isUnified &&\n st.sourceTokens?.some((source) => sameTokenOption(source, token)),\n ),\n );\n }\n if (editingAssetIndex === null) return false;\n const st = activeSelectedTokens[editingAssetIndex];\n return sameTokenOption(st, token);\n };\n\n const isGroupUnifiedSelectedInOtherSlot = (\n group: (typeof groupedFiltered)[0],\n ) => {\n if (allowSelectedTokenRemoval) return false;\n const relevantTokens = isMulti\n ? activeSelectedTokens\n : activeSelectedTokens.filter((_, idx) => idx !== editingAssetIndex);\n return relevantTokens.some(\n (st) => st.isUnified && st.unifiedSymbol === group.symbol,\n );\n };\n\n const isGroupUnifiedSelectedInCurrentSlot = (\n group: (typeof groupedFiltered)[0],\n ) => {\n if (isMulti) {\n return activeSelectedTokens.some(\n (st) => st.isUnified && st.unifiedSymbol === group.symbol,\n );\n }\n if (editingAssetIndex === null) return false;\n const st = activeSelectedTokens[editingAssetIndex];\n return Boolean(st?.isUnified && st.unifiedSymbol === group.symbol);\n };\n\n const isAnyTokenInGroupSelectedInOtherSlot = (\n group: (typeof groupedFiltered)[0],\n ) => {\n if (allowSelectedTokenRemoval) return false;\n const relevantTokens = isMulti\n ? activeSelectedTokens\n : activeSelectedTokens.filter((_, idx) => idx !== editingAssetIndex);\n return relevantTokens.some(\n (st) =>\n group.tokens.some((gt) => sameTokenOption(gt, st)) ||\n (st.isUnified && st.unifiedSymbol === group.symbol),\n );\n };\n\n const selectorRows = useMemo(() => {\n if (isMulti) {\n return groupedFiltered.map((group) => ({\n fiat: group.totalFiat,\n group,\n key: `group:${group.symbol}`,\n kind: \"group\" as const,\n label: group.symbol,\n searchScore: query.trim()\n ? Math.min(\n ...group.tokens.map(\n (token) =>\n getTokenSearchRank(token, query)?.score ??\n Number.MAX_SAFE_INTEGER,\n ),\n )\n : 0,\n }));\n }\n\n const rows: Array<\n | {\n fiat: number;\n group: (typeof groupedFiltered)[number];\n key: string;\n kind: \"group\";\n label: string;\n searchScore: number;\n }\n | {\n fiat: number;\n key: string;\n kind: \"token\";\n label: string;\n searchScore: number;\n token: SwapTokenOption;\n }\n > = [];\n const hasQuery = Boolean(query.trim());\n const getSearchScore = (token: SwapTokenOption) =>\n hasQuery\n ? (getTokenSearchRank(token, query)?.score ?? Number.MAX_SAFE_INTEGER)\n : 0;\n const isVisibleTokenRow = (token: SwapTokenOption) =>\n showBelowMinimumInline ||\n getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(token) ||\n isPrioritySearchMatch(token, query);\n\n for (const group of groupedFiltered) {\n if (!group.isUnifiedCandidate) {\n for (const token of group.tokens) {\n if (!isVisibleTokenRow(token)) continue;\n rows.push({\n fiat: getTokenFiatValue(token),\n key: `token:${token.chainId}:${token.contractAddress}`,\n kind: \"token\",\n label: `${token.symbol} ${token.chainName}`,\n searchScore: getSearchScore(token),\n token,\n });\n }\n continue;\n }\n\n const unifiedSelectedInOther = isGroupUnifiedSelectedInOtherSlot(group);\n const unifiedSelectedInCurrent =\n isGroupUnifiedSelectedInCurrentSlot(group);\n const anyIndividualSelectedInOther =\n isAnyTokenInGroupSelectedInOtherSlot(group);\n const anyIndividualSelectedInCurrent = group.tokens.some(\n isTokenSelectedInCurrentSlot,\n );\n const shouldHideUnifiedRow =\n anyIndividualSelectedInOther ||\n anyIndividualSelectedInCurrent ||\n (group.totalFiat < MIN_FIAT_THRESHOLD &&\n !isUnifiedSelectedForVisibility(group.symbol));\n const shouldHideIndividualRows =\n unifiedSelectedInOther || unifiedSelectedInCurrent;\n\n if (!unifiedSelectedInOther && !shouldHideUnifiedRow) {\n rows.push({\n fiat: group.totalFiat,\n group,\n key: `group:${group.symbol}`,\n kind: \"group\",\n label: group.symbol,\n searchScore: hasQuery\n ? Math.min(\n ...group.tokens.map(\n (token) =>\n getTokenSearchRank(token, query)?.score ??\n Number.MAX_SAFE_INTEGER,\n ),\n )\n : 0,\n });\n }\n\n if (!shouldHideIndividualRows) {\n for (const token of group.tokens) {\n if (!isVisibleTokenRow(token)) continue;\n rows.push({\n fiat: getTokenFiatValue(token),\n key: `token:${token.chainId}:${token.contractAddress}`,\n kind: \"token\",\n label: `${token.symbol} ${token.chainName}`,\n searchScore: getSearchScore(token),\n token,\n });\n }\n }\n }\n\n return rows.sort((a, b) => {\n if (hasQuery && a.searchScore !== b.searchScore) {\n return a.searchScore - b.searchScore;\n }\n if (a.fiat !== b.fiat) return b.fiat - a.fiat;\n if (a.kind !== b.kind) return a.kind === \"group\" ? -1 : 1;\n return a.label.localeCompare(b.label);\n });\n }, [\n groupedFiltered,\n isMulti,\n isGroupUnifiedSelectedInCurrentSlot,\n isGroupUnifiedSelectedInOtherSlot,\n isAnyTokenInGroupSelectedInOtherSlot,\n isTokenSelectedInCurrentSlot,\n isTokenSelectedForVisibility,\n isUnifiedSelectedForVisibility,\n query,\n showBelowMinimumInline,\n ]);\n\n const handleFilterTabClick = (tab: FilterTab, chainId = selectedChainFilter) => {\n setActiveTab(tab);\n if (!autoSelectFilterTabs || !isMulti) return;\n if (tab === \"custom\") {\n onFilterTabSelect?.(tab);\n return;\n }\n if (\n onFilterTabSelect &&\n (tab === \"all\" || filterTabBehavior === \"source-pool\" || chainId !== null)\n ) {\n // A chain-scoped selection must not reuse the all-chain quote's sources.\n onFilterTabSelect(tab, chainId === null ? undefined : getFilterTabTokens(tab, chainId));\n return;\n }\n if (onSelectionChange) emitSelectionChange(getFilterTabTokens(tab, chainId), tab);\n };\n\n const handleChainFilterChange = (chainId: number | null) => {\n setSelectedChainFilter(chainId);\n if (activeTab !== \"custom\") handleFilterTabClick(activeTab, chainId);\n closeChainSelector();\n };\n\n const getEditedSelectionTab = (): FilterTab =>\n activeTab === \"native\" || activeTab === \"stables\" ? activeTab : \"custom\";\n\n const handleClearSelection = () => {\n if (isMulti && onSelectionChange) {\n const tab = getEditedSelectionTab();\n setActiveTab(tab);\n emitSelectionChange([], tab);\n return;\n }\n onClearSelection?.();\n };\n\n const handleMultiTokenToggle = (token: SwapTokenOption) => {\n if (!autoSelectFilterTabs || !isMulti || !onSelectionChange) {\n onToggle?.(token);\n return;\n }\n\n pendingSelectionScrollTopRef.current = listRef.current?.scrollTop ?? null;\n skipNextSelectionScrollResetRef.current = true;\n const tab = getEditedSelectionTab();\n setActiveTab(tab);\n const current = mergeTokenOptions(\n activeSelectedTokens,\n lockedSelectedTokens,\n );\n const targets =\n token.isUnified && token.sourceTokens?.length\n ? token.sourceTokens\n : [token];\n const unlockedTargets = targets.filter((target) => !isLockedToken(target));\n if (unlockedTargets.length === 0) return;\n\n const allTargetsSelected = unlockedTargets.every((target) =>\n current.some((item) => sameTokenOption(item, target)),\n );\n const next = allTargetsSelected\n ? removeTokenOptions(current, unlockedTargets)\n : mergeTokenOptions(current, unlockedTargets);\n emitSelectionChange(next, tab);\n };\n\n /* ── Render a single-chain token row ── */\n const renderTokenRow = (\n token: SwapTokenOption,\n indent = false,\n isDisabledByUnified = false,\n ) => {\n const selectedInOther = !isMulti && isTokenSelectedInOtherSlot(token);\n if (selectedInOther) return null;\n\n const selectedInCurrent = isTokenSelectedInCurrentSlot(token);\n const locked = isLockedToken(token);\n const disabled = isDisabledByUnified || locked;\n return (\n {\n if (disabled) return;\n if (isMulti) {\n handleMultiTokenToggle(token);\n } else if (\n allowSelectedTokenRemoval &&\n selectedInCurrent &&\n onToggle\n ) {\n onToggle(token);\n } else onSelect(token);\n }}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"10px 14px\",\n paddingLeft: indent ? \"36px\" : \"14px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n borderBottom: \"1px solid var(--nexus-widget-surface-raised, #F0F0EF)\",\n boxSizing: \"border-box\",\n opacity: isDisabledByUnified ? 0.5 : 1,\n }}\n >\n
\n \n
\n \n
\n \n \n {token.symbol}\n \n {token.chainName && (\n
\n \n \n {token.chainName}\n \n
\n )}\n
\n \n \n \n {formatBalanceWithSymbol(token)}\n \n \n ≈ {token.balanceInFiat}\n \n \n \n );\n };\n\n /* ── Render a unified (multi-chain) group row ── */\n const renderGroupRow = (\n group: (typeof groupedFiltered)[0],\n includeIndividualRows = true,\n ) => {\n if (!group.isUnifiedCandidate) {\n return group.tokens\n .filter(\n (token) =>\n getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(token) ||\n isPrioritySearchMatch(token, query),\n )\n .map((token) => renderTokenRow(token));\n }\n\n const unifiedSelectedInOther =\n !isMulti && isGroupUnifiedSelectedInOtherSlot(group);\n if (unifiedSelectedInOther) return null;\n\n const individualTokens = group.tokens.filter(\n (token) =>\n getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(token) ||\n isPrioritySearchMatch(token, query),\n );\n const hasVisibleUnifiedRow =\n (group.totalFiat >= MIN_FIAT_THRESHOLD ||\n isUnifiedSelectedForVisibility(group.symbol)) &&\n !unifiedSelectedInOther;\n const visibleTokensCount = individualTokens.filter(\n (t) => !isTokenSelectedInOtherSlot(t),\n ).length;\n if (!hasVisibleUnifiedRow && visibleTokensCount === 0) return null;\n\n const isExpanded = expandedGroups.has(group.symbol);\n const unifiedSelectedInCurrent = isGroupUnifiedSelectedInCurrentSlot(group);\n const anyIndividualSelectedInOther =\n isAnyTokenInGroupSelectedInOtherSlot(group);\n const anyIndividualSelectedInCurrent = group.tokens.some(\n isTokenSelectedInCurrentSlot,\n );\n const selectedChildCount = group.tokens.filter(\n isTokenSelectedInCurrentSlot,\n ).length;\n const areAllChildrenSelected =\n group.tokens.length > 0 && selectedChildCount === group.tokens.length;\n const isPartiallySelected =\n selectedChildCount > 0 && selectedChildCount < group.tokens.length;\n const shouldHideUnifiedRow =\n !isMulti &&\n (anyIndividualSelectedInOther ||\n anyIndividualSelectedInCurrent ||\n (group.totalFiat < MIN_FIAT_THRESHOLD &&\n !isUnifiedSelectedForVisibility(group.symbol)));\n const shouldHideIndividualRows =\n !isMulti && (unifiedSelectedInOther || unifiedSelectedInCurrent);\n const unifiedToken: SwapTokenOption = {\n ...group.tokens[0],\n balance: String(group.totalBalRaw),\n balanceInFiat: group.totalFiatStr,\n chainId: undefined,\n chainName: \"All Chains\",\n chainLogo: \"/nexus-widget/all-chains.png\",\n contractAddress: `${group.symbol}-UNIFIED`,\n isUnified: true,\n name: group.symbol,\n sourceTokens: group.tokens,\n symbol: group.symbol,\n unifiedSymbol: group.symbol as \"USDC\" | \"USDT\" | \"ETH\",\n };\n\n return (\n \n {!shouldHideUnifiedRow && (\n {\n if (isMulti) {\n toggleGroup(group.symbol, e);\n return;\n }\n onSelect(unifiedToken);\n }}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"10px 14px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n borderBottom: \"1px solid var(--nexus-widget-surface-raised, #F0F0EF)\",\n boxSizing: \"border-box\",\n }}\n >\n
\n {\n e.stopPropagation();\n if (isMulti) handleMultiTokenToggle(unifiedToken);\n else onSelect(unifiedToken);\n }}\n style={{ cursor: \"pointer\" }}\n >\n \n
\n \n \n \n \n
\n \n {group.symbol}\n \n \n UNIFIED\n \n
\n \n \n \n
\n \n \n {group.totalBalStr}\n \n \n ≈ {group.totalFiatStr}\n \n
\n \n \n )}\n {isMulti ? (\n \n
\n {group.tokens.map((token) => renderTokenRow(token, true, false))}\n
\n \n ) : (\n includeIndividualRows &&\n !shouldHideIndividualRows &&\n individualTokens.map((token) => renderTokenRow(token))\n )}\n \n );\n };\n\n const isLoading = !staticOptions && swapBalance === null;\n const selectedAssetCount = activeSelectedTokens.length;\n const requiredUsdAmount = parseTokenAmount(requiredUsd);\n const shouldCountSelectedUsd = (token: SwapTokenOption, value: Decimal) =>\n value.gt(0) && (isLockedToken(token) || value.gte(MIN_FIAT_THRESHOLD));\n const selectedUsdAmount = activeSelectedTokens.reduce((sum, token) => {\n if (token.isUnified && token.sourceTokens?.length) {\n return sum.plus(\n token.sourceTokens.reduce((sourceSum, source) => {\n const value =\n parseTokenAmount(source.balanceInFiat) ?? new Decimal(0);\n return shouldCountSelectedUsd(source, value)\n ? sourceSum.plus(value)\n : sourceSum;\n }, new Decimal(0)),\n );\n }\n const value = parseTokenAmount(token.balanceInFiat) ?? new Decimal(0);\n return shouldCountSelectedUsd(token, value) ? sum.plus(value) : sum;\n }, new Decimal(0));\n const selectionDeficitUsdAmount =\n requiredUsdAmount && selectedUsdAmount.lt(requiredUsdAmount)\n ? requiredUsdAmount.minus(selectedUsdAmount)\n : new Decimal(0);\n const hasSelectionShortfall = Boolean(\n requiredUsdAmount &&\n requiredUsdAmount.gt(0) &&\n selectionDeficitUsdAmount.gt(0),\n );\n const shouldShowSelectionProgress = Boolean(\n isMulti && hasSelectionShortfall,\n );\n const selectionProgressPercent =\n shouldShowSelectionProgress && requiredUsdAmount\n ? Decimal.min(\n 100,\n selectedUsdAmount.div(requiredUsdAmount).mul(100),\n ).toNumber()\n : 0;\n const subtitle = isMulti\n ? `${selectedAssetCount} asset${selectedAssetCount === 1 ? \"\" : \"s\"} selected`\n : \"\";\n\n useEffect(() => {\n setPortalRoot(\n selectorRef.current?.closest(\n \"[data-nexus-widget-root]\",\n ) as HTMLElement | null,\n );\n }, []);\n\n useEffect(() => {\n return () => {\n if (chainCloseTimerRef.current) {\n clearTimeout(chainCloseTimerRef.current);\n }\n };\n }, []);\n\n const openChainSelector = () => {\n if (chainCloseTimerRef.current) {\n clearTimeout(chainCloseTimerRef.current);\n chainCloseTimerRef.current = null;\n }\n setChainQuery(\"\");\n setIsChainSelectorClosing(false);\n setShowChainSelector(true);\n };\n\n const closeChainSelector = () => {\n if (chainCloseTimerRef.current) {\n clearTimeout(chainCloseTimerRef.current);\n }\n setIsChainSelectorClosing(true);\n chainCloseTimerRef.current = setTimeout(() => {\n setShowChainSelector(false);\n setIsChainSelectorClosing(false);\n chainCloseTimerRef.current = null;\n }, CHAIN_SELECTOR_CLOSE_MS);\n };\n\n const chainOptions = useMemo(() => {\n const options = new Map();\n\n for (const chain of swapSupportedChains ?? []) {\n if (\n !sdkSwapSupportedChainIds &&\n !SWAP_CHAIN_DISPLAY_ORDER_SET.has(chain.id)\n ) {\n continue;\n }\n if (!isSwapSupportedBySdkChainList(chain.id, swapSupportedChains)) {\n continue;\n }\n options.set(chain.id, {\n contractAddress: \"\",\n symbol: \"\",\n name: getShortChainName(chain.id, chain.name),\n decimals: 18,\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n chainId: chain.id,\n chainName: getShortChainName(chain.id, chain.name),\n chainLogo: CHAIN_METADATA[chain.id]?.logo ?? chain.logo,\n });\n }\n\n for (const token of allTokens) {\n if (\n !token.chainId ||\n (!sdkSwapSupportedChainIds &&\n !SWAP_CHAIN_DISPLAY_ORDER_SET.has(token.chainId)) ||\n !isSwapSupportedBySdkChainList(token.chainId, swapSupportedChains)\n ) {\n continue;\n }\n if (!options.has(token.chainId)) {\n options.set(token.chainId, token);\n }\n }\n\n return Array.from(options.values()).sort(compareChainsBySwapDisplayOrder);\n }, [allTokens, sdkSwapSupportedChainIds, swapSupportedChains]);\n\n const selectedChainToken =\n selectedChainFilter === null\n ? undefined\n : chainOptions.find((token) => token.chainId === selectedChainFilter);\n const selectedChainLabel =\n selectedChainFilter === null\n ? \"All chains\"\n : selectedChainToken?.chainName || \"Chain\";\n\n const handleAutoSelectTokens = () => {\n handleFilterTabClick(\"all\");\n };\n\n const handleSelectManually = () => {\n handleFilterTabClick(\"custom\");\n };\n\n const handleDone = () => {\n if (hasSelectionShortfall) return;\n onDone?.(\n isMulti\n ? mergeTokenOptions(draftSelectedTokens, lockedSelectedTokens)\n : undefined,\n );\n };\n\n return (\n \n {/* Drawer Handle */}\n \n \n \n\n {/* Header */}\n \n \n \n \n \n \n {title}\n \n {subtitle && (\n \n {subtitle}\n \n )}\n \n {isMulti &&\n selectedAssetCount > 0 &&\n (onClearSelection || onSelectionChange) && (\n \n Deselect all\n \n )}\n \n\n {/* Search */}\n
\n \n \n setIsSearchFocused(false)}\n onChange={(e) => setQuery(e.target.value)}\n onFocus={() => setIsSearchFocused(true)}\n placeholder=\"Search token, chain or address\"\n style={{\n flex: 1,\n backgroundColor: \"transparent\",\n border: \"none\",\n outline: \"none\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: 14,\n color: \"var(--nexus-widget-text-strong, #161615)\",\n minWidth: 0,\n }}\n value={query}\n />\n {query && (\n setQuery(\"\")}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: 0,\n }}\n >\n \n \n )}\n {/* Chain Selector Badge */}\n \n {selectedChainFilter === null ? (\n \n ) : (\n \n )}\n \n {selectedChainLabel}\n \n \n \n
\n \n\n {/* Filter tabs */}\n \n {visibleFilterTabs.map((tab) => (\n handleFilterTabClick(tab.key)}\n style={{\n flex: 1,\n padding: \"6px 0\",\n backgroundColor:\n activeTab === tab.key ? \"var(--nexus-widget-surface-active, #FFFFFE)\" : \"transparent\",\n border: \"none\",\n borderRadius: 6,\n cursor: \"pointer\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: 13,\n fontWeight: 500,\n color: activeTab === tab.key ? \"var(--nexus-widget-text-strong, #161615)\" : \"var(--nexus-widget-text-secondary, #848483)\",\n boxShadow:\n activeTab === tab.key ? \"0px 1px 2px var(--nexus-widget-shadow-soft, rgba(0,0,0,0.05))\" : \"none\",\n transition: \"all 0.15s\",\n }}\n >\n {autoSelectFilterTabs && tab.key === \"all\" ? \"Any token\" : tab.label}\n \n ))}\n \n\n {/* Token list */}\n \n {isLoading ? (\n \n \n \n Loading assets…\n

\n \n ) : aboveMin.length === 0 && belowMin.length === 0 ? (\n \n No tokens found\n

\n ) : (\n
\n {groupedFiltered.length > 0 && (\n \n {selectorRows.map((row) =>\n row.kind === \"group\"\n ? renderGroupRow(row.group, isMulti)\n : renderTokenRow(row.token),\n )}\n
\n )}\n\n {belowMin.length > 0 && (\n \n setShowBelowMin((v) => !v)}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"11px 12px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n boxSizing: \"border-box\",\n }}\n >\n \n \n \n \n \n \n Tokens below minimum\n \n \n {showBelowMin\n ? \"Tokens under $1 are unavailable for swaps\"\n : \"Hidden to prevent failed swaps\"}\n \n \n \n \n {/* Small token logo cluster */}\n
\n {belowMin.slice(0, 3).map((t, i) =>\n 0 ? -6 : 0,\n }}\n />,\n )}\n {belowMin.length > 3 && (\n \n +{belowMin.length - 3}\n
\n )}\n \n {showBelowMin ? (\n \n ) : (\n \n )}\n \n \n \n
\n {belowMin.map((token, index) => (\n \n \n \n \n {token.chainLogo && (\n \n )}\n
\n \n {token.symbol} on{\" \"}\n {token.chainName || \"Unknown chain\"}\n \n \n \n {token.balanceInFiat}\n \n \n ))}\n \n \n \n )}\n \n )}\n \n\n {/* Done button */}\n {isMulti && (\n
\n {shouldShowSelectionProgress && requiredUsdAmount && (\n \n {autoSelectFilterTabs && hasSelectionShortfall && (\n \n \n {selectedChainFilter !== null\n ? \"Your selection doesn't cover the full amount\"\n : activeTab === \"all\"\n ? \"You don't have enough balances to meet this requirement\"\n : activeTab === \"native\"\n ? \"Your native tokens don't cover the full amount\"\n : activeTab === \"stables\"\n ? \"Your stablecoins don't cover the full amount\"\n : \"Your selection doesn't cover the full amount\"}\n \n \n {selectedChainFilter !== null\n ? 'Switch to “All chains” to include more tokens.'\n : activeTab === \"all\"\n ? \"Add more tokens to your wallet\"\n : `${formatUsdBalanceLabel(selectionDeficitUsdAmount)} more is needed.`}\n \n {(activeTab === \"native\" || activeTab === \"stables\") && (\n \n \n Auto-select tokens\n \n \n Select manually\n \n
\n )}\n \n )}\n \n \n \n Required\n \n \n \n {formatUsdBalanceLabel(selectionDeficitUsdAmount)}\n {\" \"}\n more\n \n \n \n \n \n \n \n )}\n {!hasSelectionShortfall && (\n \n Done\n \n )}\n \n )}\n\n {/* Chain Selector Modal */}\n {showChainSelector &&\n (() => {\n const chainModal = (\n \n \n \n \n \n \n \n \n \n \n \n Select chain\n \n \n\n {/* Search */}\n
\n \n \n setIsChainSearchFocused(false)}\n onChange={(e) => setChainQuery(e.target.value)}\n onFocus={() => setIsChainSearchFocused(true)}\n placeholder=\"Search chains\"\n style={{\n flex: 1,\n backgroundColor: \"transparent\",\n border: \"none\",\n outline: \"none\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: 13,\n color: \"var(--nexus-widget-text-strong, #161615)\",\n }}\n value={chainQuery}\n />\n
\n \n\n {/* Chain list */}\n \n \n {\n handleChainFilterChange(null);\n }}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px 14px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n borderBottom: \"1px solid var(--nexus-widget-surface-raised, #F0F0EF)\",\n cursor: \"pointer\",\n boxSizing: \"border-box\",\n }}\n >\n \n \n \n All Chains\n \n \n\n {/* Unique chains */}\n {chainOptions\n .filter((t) =>\n (t.chainName || \"\")\n .toLowerCase()\n .includes(chainQuery.toLowerCase()),\n )\n .map((t) => (\n {\n handleChainFilterChange(t.chainId!);\n }}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px 14px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n borderBottom: \"1px solid var(--nexus-widget-surface-raised, #F0F0EF)\",\n cursor: \"pointer\",\n boxSizing: \"border-box\",\n }}\n >\n \n \n \n {t.chainName}\n \n \n ))}\n \n \n \n \n );\n return portalRoot ? createPortal(chainModal, portalRoot) : chainModal;\n })()}\n \n );\n}\n", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\n\"use client\";\nimport type { SupportedChainsAndTokensResult } from \"@avail-project/nexus-core\";\nimport { formatTokenBalance } from \"@avail-project/nexus-core/utils\";\nimport Decimal from \"decimal.js\";\nimport {\n Check,\n ChevronDown,\n ChevronUp,\n Globe,\n Info,\n Loader2,\n Minus,\n Search,\n X,\n} from \"lucide-react\";\nimport React, {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { parseAmount as parseTokenAmount } from \"../utils/amount\";\nimport { useNexusWidgetThemeStyle } from \"../theme-context\";\nimport {\n CHAIN_METADATA,\n getSdkSwapSupportedChainIds,\n getShortChainName,\n isSwapSupportedBySdkChainList,\n} from \"../../common/utils/constant\";\nimport type { UserAsset } from \"../../nexus/NexusProvider\";\nimport { NEXUS_WIDGET_FAST_SPINNER_ANIMATION } from \"../theme\";\n\nconst tabularNums: React.CSSProperties = {\n fontFeatureSettings: '\"tnum\"',\n fontVariantNumeric: \"tabular-nums\",\n};\n\nconst brand = \"var(--foreground-brand)\";\n\nexport interface SwapTokenOption {\n /** Decimal amount without a token symbol; labels are formatted at render time. */\n balance: string;\n balanceInFiat: string;\n chainId?: number;\n chainLogo?: string;\n chainName?: string;\n contractAddress: string;\n decimals: number;\n isUnified?: boolean;\n logo?: string;\n name: string;\n priceUSD?: number | string;\n sourceTokens?: SwapTokenOption[];\n symbol: string;\n unifiedSymbol?: \"USDC\" | \"USDT\" | \"ETH\";\n userAmount?: string;\n userAmountMode?: \"token\" | \"usd\";\n userAmountUsd?: string;\n}\n\ninterface SwapAssetSelectorProps {\n allowSelectedTokenRemoval?: boolean;\n allowUnified?: boolean;\n autoSelectFilterTabs?: boolean;\n editingAssetIndex?: number | null;\n filterTabBehavior?: FilterTabBehavior;\n hideCustomTab?: boolean;\n initialFilterTab?: FilterTab;\n isMulti?: boolean;\n lockedTokens?: SwapTokenOption[];\n onBack: () => void;\n onClearSelection?: () => void;\n onDone?: (tokens?: SwapTokenOption[]) => void;\n onFilterTabSelect?: (\n tab: FilterTab,\n scopedTokens?: SwapTokenOption[],\n ) => void;\n onSelect: (token: SwapTokenOption) => void;\n onSelectionChange?: (tokens: SwapTokenOption[], tab?: FilterTab) => void;\n onToggle?: (token: SwapTokenOption) => void;\n preserveSelectedBelowMinimum?: boolean;\n requiredUsd?: string;\n selectedTokens?: SwapTokenOption[];\n showBelowMinimumInline?: boolean;\n staticOptions?: SwapTokenOption[];\n swapBalance: UserAsset[] | null;\n swapSupportedChains?: SupportedChainsAndTokensResult | null;\n title: string;\n}\n\nexport function deriveTokenOptions(\n swapBalance: UserAsset[],\n swapSupportedChains?: SupportedChainsAndTokensResult | null,\n): SwapTokenOption[] {\n const tokens: SwapTokenOption[] = [];\n for (const asset of swapBalance) {\n for (const bd of asset.breakdown ?? []) {\n if (!isSwapSupportedBySdkChainList(bd.chain?.id, swapSupportedChains)) {\n continue;\n }\n if (Number.parseFloat(bd.balance ?? \"0\") <= 0) continue;\n const chainMeta = bd.chain?.id ? CHAIN_METADATA[bd.chain.id] : undefined;\n tokens.push({\n contractAddress: bd.contractAddress,\n symbol: bd.symbol ?? asset.symbol,\n name: bd.symbol ?? asset.symbol,\n logo: asset.logo ?? \"\",\n decimals: bd.decimals ?? asset.decimals ?? 18,\n balance: bd.balance,\n balanceInFiat:\n bd.balanceInFiat != null\n ? `$${Number(bd.balanceInFiat).toFixed(2)}`\n : \"$0.00\",\n chainId: bd.chain?.id,\n chainName: getShortChainName(\n bd.chain?.id,\n chainMeta?.name ?? bd.chain?.name,\n ),\n chainLogo: chainMeta?.logo ?? bd.chain?.logo,\n });\n }\n }\n const seen = new Map();\n for (const t of tokens) {\n seen.set(`${t.contractAddress.toLowerCase()}-${t.chainId}`, t);\n }\n return Array.from(seen.values());\n}\n\n/* ── Radio dot (circular) ── */\nexport const RadioDot = ({ selected }: { selected: boolean }) => (\n \n {selected && (\n \n )}\n \n);\n\nconst SelectionControl = ({\n selected,\n indeterminate = false,\n multi,\n}: {\n selected: boolean;\n indeterminate?: boolean;\n multi: boolean;\n}) => {\n if (!multi) return ;\n\n const isActive = selected || indeterminate;\n\n return (\n \n {selected && (\n \n )}\n {!selected && indeterminate && (\n \n )}\n \n );\n};\n\nfunction TokenLogo({\n src,\n label,\n size,\n fontSize,\n style,\n fallbackBackground = brand,\n fallbackColor = \"var(--nexus-widget-surface, #FFFFFE)\",\n}: {\n src?: string;\n label?: string;\n size: number;\n fontSize: number;\n style?: React.CSSProperties;\n fallbackBackground?: string;\n fallbackColor?: string;\n}) {\n const normalizedSrc = src?.trim();\n const [failed, setFailed] = useState(!normalizedSrc);\n\n useEffect(() => {\n setFailed(!normalizedSrc);\n }, [normalizedSrc]);\n\n if (!failed && normalizedSrc) {\n return (\n setFailed(true)}\n src={normalizedSrc}\n style={{\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").slice(0, 2).toUpperCase()}\n \n );\n}\n\nconst getChainLogo = (\n token?: Pick | null,\n) => {\n if (!token) return undefined;\n return token.chainId\n ? (CHAIN_METADATA[token.chainId]?.logo ?? token.chainLogo)\n : token.chainLogo;\n};\n\n/* ── Chain logo cluster ── */\nconst ChainLogos = ({ tokens }: { tokens: SwapTokenOption[] }) => {\n const themeStyle = useNexusWidgetThemeStyle();\n const clusterRef = useRef(null);\n const closeTimerRef = useRef | null>(null);\n const [showTooltip, setShowTooltip] = useState(false);\n const [tooltipRect, setTooltipRect] = useState(null);\n const uniqueChains = useMemo(() => {\n const seen = new Set();\n const out: {\n id: number;\n logo?: string;\n name?: string;\n balance?: string;\n balanceInFiat?: string;\n balanceValue: number;\n fiatValue: number;\n }[] = [];\n for (const t of tokens) {\n if (t.chainId && !seen.has(t.chainId)) {\n const balanceValue = parseTokenAmount(t.balance)?.toNumber() ?? 0;\n seen.add(t.chainId);\n out.push({\n id: t.chainId,\n logo: getChainLogo(t),\n name: getShortChainName(t.chainId, t.chainName),\n balance: t.balance,\n balanceInFiat: t.balanceInFiat,\n balanceValue:\n Number.isNaN(balanceValue) || !Number.isFinite(balanceValue)\n ? 0\n : balanceValue,\n fiatValue: getTokenFiatValue(t),\n });\n }\n }\n return out.sort((a, b) => {\n if (a.fiatValue !== b.fiatValue) return b.fiatValue - a.fiatValue;\n if (a.balanceValue !== b.balanceValue) {\n return b.balanceValue - a.balanceValue;\n }\n return (a.name ?? \"\").localeCompare(b.name ?? \"\");\n });\n }, [tokens]);\n\n const maxShow = 3;\n const shown = uniqueChains.slice(0, maxShow);\n const openTooltip = () => {\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n setTooltipRect(clusterRef.current?.getBoundingClientRect() ?? null);\n setShowTooltip(true);\n };\n const closeTooltip = () => {\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n closeTimerRef.current = setTimeout(() => {\n setShowTooltip(false);\n closeTimerRef.current = null;\n }, 120);\n };\n useEffect(() => {\n return () => {\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n };\n }, []);\n const showTooltipAbove = tooltipRect ? tooltipRect.top > 240 : true;\n const tooltip =\n showTooltip && uniqueChains.length > 1 && tooltipRect\n ? createPortal(\n \n \n UNIFIED · {uniqueChains.length} CHAINS\n \n {tokens\n .reduce((sum, token) => sum + getTokenFiatValue(token), 0)\n .toLocaleString(undefined, {\n currency: \"USD\",\n maximumFractionDigits: 2,\n style: \"currency\",\n })}\n \n \n {uniqueChains.map((chain) => (\n \n \n \n \n {chain.name || \"Unknown chain\"}\n \n \n \n {chain.balance\n ? formatTokenAmountDisplay(chain.balance)\n : chain.balanceInFiat || \"0\"}\n \n \n ))}\n ,\n document.body,\n )\n : null;\n\n return (\n \n {tooltip}\n {shown.map((c) => (\n \n ))}\n \n {uniqueChains.length} chain{uniqueChains.length !== 1 ? \"s\" : \"\"}\n \n \n );\n};\n\n/* ── Filter tabs ── */\ntype FilterTab = \"all\" | \"native\" | \"stables\" | \"custom\";\ntype FilterTabBehavior = \"select-all\" | \"source-pool\";\nconst FILTER_TABS: { key: FilterTab; label: string }[] = [\n { key: \"all\", label: \"All\" },\n { key: \"native\", label: \"Native\" },\n { key: \"stables\", label: \"Stables\" },\n { key: \"custom\", label: \"Manual\" },\n];\nconst STABLE_SYMBOLS = new Set([\n \"AUSD\",\n \"BDO\",\n \"BRZ\",\n \"BTCUSD\",\n \"BUSD\",\n \"bnbUSD\",\n \"crvUSD\",\n \"CUSD\",\n \"DAI\",\n \"DAI.e\",\n \"dEURO\",\n \"DUSD\",\n \"EURA\",\n \"EURC\",\n \"EURCV\",\n \"EURe\",\n \"EURS\",\n \"EURT\",\n \"eUSD\",\n \"frxUSD\",\n \"GHO\",\n \"GUSD\",\n \"JUST\",\n \"jEUR\",\n \"JUSD\",\n \"LUSD\",\n \"rUSD\",\n \"RLUSD\",\n \"sUSD\",\n \"svJUSD\",\n \"TUSD\",\n \"USDC\",\n \"USDC.e\",\n \"USDS\",\n \"USDT\",\n \"USDT0\",\n \"USDT.e\",\n \"ctUSD\",\n \"PYUSD\",\n \"USDe\",\n \"xDAI\",\n \"USD0\",\n \"USDM\",\n]);\nconst normalizeTokenGroupSymbol = (symbol: string) =>\n symbol\n .trim()\n .toUpperCase()\n .replaceAll(\"₮\", \"T\")\n .replaceAll(/[^A-Z0-9]/g, \"\");\nconst STABLE_SYMBOL_KEYS = new Set(\n Array.from(STABLE_SYMBOLS, normalizeTokenGroupSymbol),\n);\n\nconst isStableToken = (token: SwapTokenOption) =>\n STABLE_SYMBOL_KEYS.has(normalizeTokenGroupSymbol(token.symbol));\n\nfunction isNativeToken(t: SwapTokenOption) {\n if (isNativeLikeAddress(t.contractAddress)) return true;\n\n const sym = t.symbol.toUpperCase();\n const chain = (t.chainName || \"\").toLowerCase();\n\n if (sym === \"ETH\")\n return (\n !chain.includes(\"bnb\") &&\n !chain.includes(\"bsc\") &&\n !chain.includes(\"polygon\") &&\n !chain.includes(\"monad\") &&\n !chain.includes(\"hyperevm\")\n );\n if (sym === \"POL\" || sym === \"MATIC\") return chain.includes(\"polygon\");\n if (sym === \"HYPE\") return chain.includes(\"hyperevm\");\n if (sym === \"MON\") return chain.includes(\"monad\");\n if (sym === \"BNB\") return chain.includes(\"bnb\") || chain.includes(\"bsc\");\n if (sym === \"AVAX\") return chain.includes(\"avalanche\");\n if (sym === \"FTM\") return chain.includes(\"fantom\");\n if (sym === \"CELO\") return chain.includes(\"celo\");\n if (sym === \"SUI\") return chain.includes(\"sui\");\n if (sym === \"APT\") return chain.includes(\"aptos\");\n if (sym === \"SOL\") return chain.includes(\"solana\");\n return false;\n}\n\nconst MIN_FIAT_THRESHOLD = 1;\nconst CHAIN_SELECTOR_CLOSE_MS = 220;\nconst MODAL_HEIGHT_TRANSITION_MS = 260;\nconst modalHeightTransitionStyle = {\n interpolateSize: \"allow-keywords\",\n} as React.CSSProperties;\nconst modalHeightTransition = `height ${MODAL_HEIGHT_TRANSITION_MS}ms ease, max-height ${MODAL_HEIGHT_TRANSITION_MS}ms ease`;\nexport const SWAP_CHAIN_DISPLAY_ORDER = [\n 1, // Ethereum\n 42161, // Arbitrum\n 8453, // Base\n 137, // Polygon\n 10, // OP\n 999, // HyperEVM\n 56, // BSC\n // 43114, // Avalanche\n 143, // Monad\n 4326, // MegaETH\n 4114, // Citrea\n 8217, // Kaia\n 534352, // Scroll\n] as const;\nconst SWAP_CHAIN_DISPLAY_ORDER_RANK = new Map(\n SWAP_CHAIN_DISPLAY_ORDER.map((chainId, index) => [chainId, index]),\n);\nexport const SWAP_CHAIN_DISPLAY_ORDER_SET = new Set(\n SWAP_CHAIN_DISPLAY_ORDER,\n);\nexport const sortChainIdsBySwapDisplayOrder = (chainIds: number[]) =>\n [...chainIds].sort((a, b) => {\n const aRank =\n SWAP_CHAIN_DISPLAY_ORDER_RANK.get(a) ?? Number.MAX_SAFE_INTEGER;\n const bRank =\n SWAP_CHAIN_DISPLAY_ORDER_RANK.get(b) ?? Number.MAX_SAFE_INTEGER;\n if (aRank !== bRank) return aRank - bRank;\n\n const aName = CHAIN_METADATA[a]?.name ?? String(a);\n const bName = CHAIN_METADATA[b]?.name ?? String(b);\n return aName.localeCompare(bName);\n });\nexport const compareChainsBySwapDisplayOrder = <\n T extends { chainId?: number; chainName?: string },\n>(\n a: T,\n b: T,\n) => {\n const aRank =\n SWAP_CHAIN_DISPLAY_ORDER_RANK.get(a.chainId ?? -1) ??\n Number.MAX_SAFE_INTEGER;\n const bRank =\n SWAP_CHAIN_DISPLAY_ORDER_RANK.get(b.chainId ?? -1) ??\n Number.MAX_SAFE_INTEGER;\n if (aRank !== bRank) return aRank - bRank;\n return (a.chainName ?? \"\").localeCompare(b.chainName ?? \"\");\n};\nconst UNIFIED_MAINNET_CHAIN_IDS = new Set([\n 1, 10, 56, 137, 143, 999, 4114, 8217, 8453, 42161, 43114, 534352, 4326,\n]);\nconst UNIFIED_USDC_SYMBOL_KEYS = new Set([\"USDC\", \"USDCE\", \"USDM\"]);\nconst UNIFIED_USDT_SYMBOL_KEYS = new Set([\"USDT\", \"USDT0\", \"USDTE\"]);\n\nconst getTokenFiatValue = (token: Pick) => {\n const parsed = parseTokenAmount(token.balanceInFiat)?.toNumber() ?? 0;\n return isNaN(parsed) || !isFinite(parsed) ? 0 : parsed;\n};\n\nconst formatBalanceWithSymbol = (\n token: Pick,\n) => {\n const symbol = token.symbol?.trim() || \"\";\n const formatted = formatTokenAmountDisplay(token.balance);\n return symbol ? `${formatted} ${symbol}` : formatted;\n};\n\nconst compareTokensByUsdBalance = (a: SwapTokenOption, b: SwapTokenOption) => {\n const fiatDelta = getTokenFiatValue(b) - getTokenFiatValue(a);\n if (fiatDelta !== 0) return fiatDelta;\n\n const aBalance = parseTokenAmount(a.balance) ?? new Decimal(0);\n const bBalance = parseTokenAmount(b.balance) ?? new Decimal(0);\n const balanceDelta = bBalance.cmp(aBalance);\n if (balanceDelta !== 0) return balanceDelta;\n\n const chainDelta = compareChainsBySwapDisplayOrder(a, b);\n if (chainDelta !== 0) return chainDelta;\n\n return `${a.symbol} ${a.chainName}`.localeCompare(\n `${b.symbol} ${b.chainName}`,\n );\n};\n\nconst sortTokensByUsdBalance = (tokens: SwapTokenOption[]) =>\n [...tokens].sort(compareTokensByUsdBalance);\n\nexport const formatTokenAmountDisplay = (value: unknown) => {\n const amount = parseTokenAmount(value) ?? new Decimal(0);\n const abs = amount.abs();\n\n if (amount.isZero()) return \"0\";\n\n const compactUnits = [\n { suffix: \"T\", value: new Decimal(1_000_000_000_000) },\n { suffix: \"B\", value: new Decimal(1_000_000_000) },\n { suffix: \"M\", value: new Decimal(1_000_000) },\n ];\n\n for (const unit of compactUnits) {\n if (abs.gte(unit.value)) {\n return `${amount\n .div(unit.value)\n .toDecimalPlaces(4, Decimal.ROUND_DOWN)\n .toFixed()}${unit.suffix}`;\n }\n }\n\n const minDisplay = new Decimal(\"0.00000001\");\n if (amount.gt(0) && amount.lt(minDisplay)) {\n return `>${minDisplay.toFixed()}`;\n }\n\n return amount.toDecimalPlaces(8, Decimal.ROUND_DOWN).toFixed();\n};\n\nconst addThousandsSeparators = (value: string) => {\n const [integerPart, decimalPart] = value.split(\".\");\n const withSeparators = integerPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n return decimalPart === undefined\n ? withSeparators\n : `${withSeparators}.${decimalPart}`;\n};\n\nexport const formatUsdBalanceLabel = (value: unknown) => {\n const amount = parseTokenAmount(value) ?? new Decimal(0);\n const abs = amount.abs();\n\n if (amount.isZero()) return \"$0.00\";\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n\n const compactUnits = [\n { suffix: \"T\", value: new Decimal(1_000_000_000_000) },\n { suffix: \"B\", value: new Decimal(1_000_000_000) },\n { suffix: \"M\", value: new Decimal(1_000_000) },\n ];\n\n for (const unit of compactUnits) {\n if (abs.gte(unit.value)) {\n return `$${amount\n .div(unit.value)\n .toDecimalPlaces(4, Decimal.ROUND_DOWN)\n .toFixed()}${unit.suffix}`;\n }\n }\n\n return `$${addThousandsSeparators(amount.toDecimalPlaces(2).toFixed(2))}`;\n};\n\nexport const formatSelectedTokenBalanceLabel = (\n token?: Pick,\n) => {\n if (!token) return \"\";\n const symbol = token.symbol || \"\";\n const formatted = formatTokenAmountDisplay(token.balance);\n return symbol ? `${formatted} ${symbol}` : formatted;\n};\n\nconst getSearchTerms = (query: string) =>\n query.toLowerCase().trim().split(/\\s+/).filter(Boolean);\n\nconst includesTerm = (value: string | undefined, term: string) =>\n (value ?? \"\").toLowerCase().includes(term);\n\nconst startsWithTerm = (value: string | undefined, term: string) =>\n (value ?? \"\").toLowerCase().startsWith(term);\n\nconst equalsTerm = (value: string | undefined, term: string) =>\n (value ?? \"\").toLowerCase() === term;\n\nexport const getTokenSearchRank = (\n token: Pick<\n SwapTokenOption,\n \"symbol\" | \"name\" | \"chainName\" | \"contractAddress\"\n >,\n query: string,\n) => {\n const terms = getSearchTerms(query);\n if (terms.length === 0) return null;\n\n let matchedTerms = 0;\n let symbolExactTerms = 0;\n let symbolPrefixTerms = 0;\n let symbolIncludeTerms = 0;\n let namePrefixTerms = 0;\n let tokenExactTerms = 0;\n let tokenPrefixTerms = 0;\n let tokenIncludeTerms = 0;\n let chainExactTerms = 0;\n let chainPrefixTerms = 0;\n let chainIncludeTerms = 0;\n let addressTerms = 0;\n\n for (const term of terms) {\n const symbolExact = equalsTerm(token.symbol, term);\n const symbolPrefix = symbolExact || startsWithTerm(token.symbol, term);\n const symbolInclude = symbolPrefix || includesTerm(token.symbol, term);\n const nameExact = equalsTerm(token.name, term);\n const namePrefix = nameExact || startsWithTerm(token.name, term);\n const nameInclude = namePrefix || includesTerm(token.name, term);\n const tokenExact = symbolExact || nameExact;\n const tokenPrefix = tokenExact || symbolPrefix || namePrefix;\n const tokenInclude = tokenPrefix || symbolInclude || nameInclude;\n const chainExact = equalsTerm(token.chainName, term);\n const chainPrefix = chainExact || startsWithTerm(token.chainName, term);\n const chainInclude = chainPrefix || includesTerm(token.chainName, term);\n const addressMatch = includesTerm(token.contractAddress, term);\n\n if (tokenInclude || chainInclude || addressMatch) matchedTerms += 1;\n if (symbolExact) symbolExactTerms += 1;\n if (symbolPrefix) symbolPrefixTerms += 1;\n if (symbolInclude) symbolIncludeTerms += 1;\n if (namePrefix) namePrefixTerms += 1;\n if (tokenExact) tokenExactTerms += 1;\n if (tokenPrefix) tokenPrefixTerms += 1;\n if (tokenInclude) tokenIncludeTerms += 1;\n if (chainExact) chainExactTerms += 1;\n if (chainPrefix) chainPrefixTerms += 1;\n if (chainInclude) chainIncludeTerms += 1;\n if (addressMatch) addressTerms += 1;\n }\n\n const allTermsMatched = matchedTerms === terms.length;\n if (!allTermsMatched) return null;\n\n if (\n terms.length > 1 &&\n chainIncludeTerms > 0 &&\n symbolIncludeTerms === 0 &&\n addressTerms === 0 &&\n namePrefixTerms === 0\n ) {\n return null;\n }\n\n const hasTokenMatch = tokenIncludeTerms > 0;\n const hasChainMatch = chainIncludeTerms > 0;\n const isTokenChainMatch = allTermsMatched && hasTokenMatch && hasChainMatch;\n\n let score = 20;\n if (isTokenChainMatch) {\n if (symbolExactTerms > 0 && chainExactTerms > 0) score = 0;\n else if (symbolExactTerms > 0 && chainPrefixTerms > 0) score = 1;\n else if (symbolExactTerms > 0 && chainIncludeTerms > 0) score = 2;\n else if (symbolPrefixTerms > 0 && chainIncludeTerms > 0) score = 3;\n else if (symbolIncludeTerms > 0 && chainIncludeTerms > 0) score = 4;\n else if (namePrefixTerms > 0 && chainIncludeTerms > 0) score = 5;\n else score = 6;\n } else if (symbolExactTerms > 0) score = 7;\n else if (symbolPrefixTerms > 0) score = 8;\n else if (symbolIncludeTerms > 0) score = 9;\n else if (tokenExactTerms > 0) score = 10;\n else if (tokenPrefixTerms > 0) score = 11;\n else if (tokenIncludeTerms > 0) score = 12;\n else if (chainExactTerms > 0) score = 13;\n else if (chainPrefixTerms > 0) score = 14;\n else if (chainIncludeTerms > 0) score = 15;\n else if (addressTerms > 0) score = 16;\n\n return {\n allTermsMatched,\n isTokenChainMatch,\n matchedTerms,\n score,\n tokenExactTerms,\n tokenIncludeTerms,\n };\n};\n\nconst isPrioritySearchMatch = (token: SwapTokenOption, query: string) => {\n const rank = getTokenSearchRank(token, query);\n return Boolean(\n rank &&\n (rank.isTokenChainMatch ||\n rank.tokenExactTerms > 0 ||\n rank.allTermsMatched),\n );\n};\n\nconst compareTokensBySearch = (\n a: SwapTokenOption,\n b: SwapTokenOption,\n query: string,\n) => {\n const aRank = getTokenSearchRank(a, query);\n const bRank = getTokenSearchRank(b, query);\n const aScore = aRank?.score ?? Number.MAX_SAFE_INTEGER;\n const bScore = bRank?.score ?? Number.MAX_SAFE_INTEGER;\n if (aScore !== bScore) return aScore - bScore;\n\n const aMatched = aRank?.matchedTerms ?? 0;\n const bMatched = bRank?.matchedTerms ?? 0;\n if (aMatched !== bMatched) return bMatched - aMatched;\n\n const aFiat = getTokenFiatValue(a);\n const bFiat = getTokenFiatValue(b);\n if (aFiat !== bFiat) return bFiat - aFiat;\n\n return `${a.symbol} ${a.chainName}`.localeCompare(\n `${b.symbol} ${b.chainName}`,\n );\n};\n\nfunction getUnifiedSymbol(token: Pick) {\n if (token.chainId && !UNIFIED_MAINNET_CHAIN_IDS.has(token.chainId)) {\n return null;\n }\n\n const symbol = normalizeTokenGroupSymbol(token.symbol);\n if (UNIFIED_USDC_SYMBOL_KEYS.has(symbol)) return \"USDC\" as const;\n if (UNIFIED_USDT_SYMBOL_KEYS.has(symbol)) return \"USDT\" as const;\n if (symbol === \"ETH\") return \"ETH\" as const;\n return null;\n}\n\nfunction sameTokenOption(a?: SwapTokenOption, b?: SwapTokenOption) {\n if (!a || !b) return false;\n if (a.isUnified || b.isUnified) {\n return Boolean(\n a.isUnified && b.isUnified && a.unifiedSymbol === b.unifiedSymbol,\n );\n }\n return (\n sameContractAddress(a.contractAddress, b.contractAddress) &&\n a.chainId === b.chainId\n );\n}\n\nfunction isSameTokenList(a: SwapTokenOption[], b: SwapTokenOption[]) {\n if (a.length !== b.length) return false;\n return a.every((tokenA) =>\n b.some((tokenB) => sameTokenOption(tokenA, tokenB)),\n );\n}\n\nfunction dedupeTokenOptions(tokens: SwapTokenOption[]) {\n return tokens.reduce((acc, token) => {\n if (!acc.some((item) => sameTokenOption(item, token))) {\n acc.push(token);\n }\n return acc;\n }, []);\n}\n\nfunction mergeTokenOptions(\n base: SwapTokenOption[],\n additions: SwapTokenOption[],\n) {\n return dedupeTokenOptions([...base, ...additions]);\n}\n\nfunction removeTokenOptions(\n base: SwapTokenOption[],\n removals: SwapTokenOption[],\n) {\n return base.filter(\n (token) => !removals.some((removal) => sameTokenOption(token, removal)),\n );\n}\n\nfunction isNativeLikeAddress(address?: string) {\n const normalized = (address ?? \"\").toLowerCase();\n return (\n normalized === \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\" ||\n normalized === \"0x0000000000000000000000000000000000000000\"\n );\n}\n\nfunction addressTail(address?: string) {\n const normalized = (address ?? \"\").toLowerCase();\n if (!normalized.startsWith(\"0x\")) return normalized;\n return normalized.slice(-40);\n}\n\nfunction sameContractAddress(a?: string, b?: string) {\n const normalizedA = (a ?? \"\").toLowerCase();\n const normalizedB = (b ?? \"\").toLowerCase();\n if (!normalizedA || !normalizedB) return normalizedA === normalizedB;\n if (normalizedA === normalizedB) return true;\n if (isNativeLikeAddress(normalizedA) && isNativeLikeAddress(normalizedB)) {\n return true;\n }\n return addressTail(normalizedA) === addressTail(normalizedB);\n}\n\nexport function SwapAssetSelector({\n title,\n swapBalance,\n swapSupportedChains,\n staticOptions,\n onSelect,\n onBack,\n isMulti,\n selectedTokens = [],\n editingAssetIndex = null,\n onToggle,\n onClearSelection,\n onDone,\n allowUnified = false,\n preserveSelectedBelowMinimum = false,\n showBelowMinimumInline = false,\n allowSelectedTokenRemoval = false,\n hideCustomTab = false,\n autoSelectFilterTabs = false,\n initialFilterTab = \"all\",\n filterTabBehavior = \"select-all\",\n onFilterTabSelect,\n lockedTokens = [],\n onSelectionChange,\n requiredUsd,\n}: SwapAssetSelectorProps) {\n const sdkSwapSupportedChainIds = useMemo(\n () => getSdkSwapSupportedChainIds(swapSupportedChains),\n [swapSupportedChains],\n );\n const selectorRef = useRef(null);\n const listRef = useRef(null);\n const chainCloseTimerRef = useRef | null>(null);\n const [portalRoot, setPortalRoot] = useState(null);\n const [query, setQuery] = useState(\"\");\n const normalizedInitialFilterTab =\n hideCustomTab && initialFilterTab === \"custom\" ? \"all\" : initialFilterTab;\n const [activeTab, setActiveTab] = useState(\n normalizedInitialFilterTab,\n );\n const [showBelowMin, setShowBelowMin] = useState(false);\n const [isSearchFocused, setIsSearchFocused] = useState(false);\n const [showChainSelector, setShowChainSelector] = useState(false);\n const [isChainSelectorClosing, setIsChainSelectorClosing] = useState(false);\n const [chainQuery, setChainQuery] = useState(\"\");\n const [selectedChainFilter, setSelectedChainFilter] = useState(\n null,\n );\n const [isChainSearchFocused, setIsChainSearchFocused] = useState(false);\n const stableListHeightRef = useRef(0);\n const pendingSelectionScrollTopRef = useRef(null);\n const skipNextSelectionScrollResetRef = useRef(false);\n const [stableListHeight, setStableListHeight] = useState(null);\n const lockedSelectedTokens = useMemo(\n () => dedupeTokenOptions(lockedTokens),\n [lockedTokens],\n );\n const isLockedToken = useCallback(\n (token: SwapTokenOption) =>\n lockedSelectedTokens.some((locked) => sameTokenOption(locked, token)),\n [lockedSelectedTokens],\n );\n const [draftSelectedTokens, setDraftSelectedTokens] = useState<\n SwapTokenOption[]\n >(() => mergeTokenOptions(selectedTokens, lockedSelectedTokens));\n useEffect(() => {\n if (!isMulti) return;\n setDraftSelectedTokens(\n mergeTokenOptions(selectedTokens, lockedSelectedTokens),\n );\n }, [isMulti, lockedSelectedTokens, selectedTokens]);\n const activeSelectedTokens = isMulti ? draftSelectedTokens : selectedTokens;\n const emitSelectionChange = useCallback(\n (tokens: SwapTokenOption[], tab: FilterTab = activeTab) => {\n const next = mergeTokenOptions(tokens, lockedSelectedTokens);\n if (isMulti) {\n setDraftSelectedTokens(next);\n }\n onSelectionChange?.(next, tab);\n },\n [activeTab, isMulti, lockedSelectedTokens, onSelectionChange],\n );\n const visibleFilterTabs = useMemo(\n () =>\n hideCustomTab\n ? FILTER_TABS.filter((tab) => tab.key !== \"custom\")\n : FILTER_TABS,\n [hideCustomTab],\n );\n\n useEffect(() => {\n if (hideCustomTab && activeTab === \"custom\") {\n setActiveTab(\"all\");\n }\n }, [activeTab, hideCustomTab]);\n\n useEffect(() => {\n setActiveTab((current) =>\n current === normalizedInitialFilterTab\n ? current\n : normalizedInitialFilterTab,\n );\n }, [normalizedInitialFilterTab]);\n\n useEffect(() => {\n if (skipNextSelectionScrollResetRef.current) {\n skipNextSelectionScrollResetRef.current = false;\n return;\n }\n if (listRef.current) {\n listRef.current.scrollTop = 0;\n }\n }, [query, activeTab, selectedChainFilter]);\n\n useLayoutEffect(() => {\n const pendingScrollTop = pendingSelectionScrollTopRef.current;\n if (pendingScrollTop === null) return;\n\n if (listRef.current) {\n listRef.current.scrollTop = pendingScrollTop;\n }\n pendingSelectionScrollTopRef.current = null;\n }, [draftSelectedTokens]);\n\n const allTokens = useMemo(() => {\n const isSwapSupportedToken = (token: SwapTokenOption) =>\n isSwapSupportedBySdkChainList(token.chainId, swapSupportedChains);\n\n const baseTokens = staticOptions\n ? staticOptions.filter(isSwapSupportedToken)\n : swapBalance\n ? deriveTokenOptions(swapBalance, swapSupportedChains)\n : [];\n\n if (!preserveSelectedBelowMinimum && lockedSelectedTokens.length === 0) {\n return sortTokensByUsdBalance(baseTokens);\n }\n\n const merged = [...baseTokens];\n const selectedSourceTokens = [\n ...activeSelectedTokens,\n ...lockedSelectedTokens,\n ].flatMap((token) =>\n token.isUnified && token.sourceTokens?.length\n ? token.sourceTokens\n : [token],\n );\n\n for (const selectedToken of selectedSourceTokens) {\n const alreadyPresent = merged.some((token) =>\n sameTokenOption(token, selectedToken),\n );\n if (!alreadyPresent) {\n merged.push(selectedToken);\n }\n }\n\n return sortTokensByUsdBalance(merged.filter(isSwapSupportedToken));\n }, [\n lockedSelectedTokens,\n preserveSelectedBelowMinimum,\n activeSelectedTokens,\n swapBalance,\n swapSupportedChains,\n staticOptions,\n ]);\n\n const getFilterTabTokens = useCallback(\n (tab: FilterTab, chainId = selectedChainFilter) => {\n let result = allTokens;\n if (chainId !== null) {\n result = result.filter((token) => token.chainId === chainId);\n }\n if (tab === \"native\") result = result.filter(isNativeToken);\n else if (tab === \"stables\") {\n result = result.filter(isStableToken);\n }\n\n if (showBelowMinimumInline) {\n return mergeTokenOptions(result, lockedSelectedTokens);\n }\n\n return mergeTokenOptions(\n result.filter(\n (token) => getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD,\n ),\n lockedSelectedTokens,\n );\n },\n [\n allTokens,\n lockedSelectedTokens,\n selectedChainFilter,\n showBelowMinimumInline,\n ],\n );\n\n /* Search + tab + chain filter */\n const filtered = useMemo(() => {\n let result = allTokens;\n if (selectedChainFilter !== null) {\n result = result.filter((t) => t.chainId === selectedChainFilter);\n }\n if (query.trim()) {\n result = result\n .filter((t) => getTokenSearchRank(t, query) !== null)\n .sort((a, b) => compareTokensBySearch(a, b, query));\n }\n if (activeTab === \"native\") result = result.filter(isNativeToken);\n else if (activeTab === \"stables\") result = result.filter(isStableToken);\n else if (activeTab === \"custom\" && !autoSelectFilterTabs)\n result = result.filter((t) => !isNativeToken(t) && !isStableToken(t));\n return result;\n }, [activeTab, allTokens, autoSelectFilterTabs, query, selectedChainFilter]);\n\n const isTokenSelectedForVisibility = useCallback(\n (token: SwapTokenOption) => {\n if (isLockedToken(token)) return true;\n if (!preserveSelectedBelowMinimum) return false;\n\n return activeSelectedTokens.some(\n (selected) =>\n sameTokenOption(selected, token) ||\n Boolean(\n selected.isUnified &&\n selected.sourceTokens?.some((source) =>\n sameTokenOption(source, token),\n ),\n ),\n );\n },\n [activeSelectedTokens, isLockedToken, preserveSelectedBelowMinimum],\n );\n\n const isUnifiedSelectedForVisibility = useCallback(\n (symbol: string) =>\n preserveSelectedBelowMinimum &&\n activeSelectedTokens.some(\n (selected) => selected.isUnified && selected.unifiedSymbol === symbol,\n ),\n [activeSelectedTokens, preserveSelectedBelowMinimum],\n );\n\n /* Split into above/below minimum */\n const { aboveMin, belowMin } = useMemo(() => {\n const above: SwapTokenOption[] = [];\n const below: SwapTokenOption[] = [];\n for (const t of filtered) {\n const fiat = getTokenFiatValue(t);\n if (\n showBelowMinimumInline ||\n fiat >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(t) ||\n isPrioritySearchMatch(t, query)\n )\n above.push(t);\n else below.push(t);\n }\n return { aboveMin: above, belowMin: below };\n }, [filtered, isTokenSelectedForVisibility, query, showBelowMinimumInline]);\n\n /* Group by symbol */\n const groupedFiltered = useMemo(() => {\n const groups: Record = {};\n for (const token of filtered) {\n const unifiedSym = allowUnified ? getUnifiedSymbol(token) : null;\n if (\n !showBelowMinimumInline &&\n unifiedSym &&\n getTokenFiatValue(token) < MIN_FIAT_THRESHOLD &&\n !isTokenSelectedForVisibility(token)\n ) {\n continue;\n }\n const key = unifiedSym ?? `${token.contractAddress}-${token.chainId}`;\n if (!groups[key]) groups[key] = [];\n groups[key].push(token);\n }\n return Object.values(groups)\n .map((group) => {\n const sortedGroup = sortTokensByUsdBalance(group);\n let totalFiatVal = 0;\n let totalBalVal = 0;\n for (const t of sortedGroup) {\n const fiatVal = getTokenFiatValue(t);\n totalFiatVal += isNaN(fiatVal) || !isFinite(fiatVal) ? 0 : fiatVal;\n const balVal = parseTokenAmount(t.balance)?.toNumber() ?? 0;\n totalBalVal += isNaN(balVal) || !isFinite(balVal) ? 0 : balVal;\n }\n const unifiedSym = allowUnified\n ? getUnifiedSymbol(sortedGroup[0])\n : null;\n const symbol = unifiedSym ?? sortedGroup[0].symbol;\n const isStable = [\"USDC\", \"USDT\", \"DAI\", \"USDM\", \"CTUSD\"].includes(\n symbol.toUpperCase(),\n );\n const maxDigits = isStable ? 2 : 6;\n const formattedBal = totalBalVal.toLocaleString(undefined, {\n minimumFractionDigits: 0,\n maximumFractionDigits: maxDigits,\n });\n\n return {\n symbol,\n logo: sortedGroup[0].logo,\n totalFiat: totalFiatVal,\n totalFiatStr: `$${totalFiatVal.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 })}`,\n totalBalStr: `${formattedBal} ${symbol}`,\n totalBalRaw: totalBalVal,\n tokens: sortedGroup,\n isUnifiedCandidate: Boolean(unifiedSym && group.length > 1),\n };\n })\n .filter((group) => {\n const hasSelectedToken = group.tokens.some(\n isTokenSelectedForVisibility,\n );\n const hasSelectedUnified = isUnifiedSelectedForVisibility(group.symbol);\n const hasPrioritySearchMatch = group.tokens.some((token) =>\n isPrioritySearchMatch(token, query),\n );\n if (showBelowMinimumInline) {\n return true;\n }\n if (group.isUnifiedCandidate) {\n return (\n group.totalFiat >= MIN_FIAT_THRESHOLD ||\n hasSelectedToken ||\n hasSelectedUnified ||\n hasPrioritySearchMatch\n );\n }\n return group.tokens.some(\n (token) =>\n getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(token) ||\n isPrioritySearchMatch(token, query),\n );\n })\n .sort((a, b) => {\n if (query.trim()) {\n const aScore = Math.min(\n ...a.tokens.map(\n (token) =>\n getTokenSearchRank(token, query)?.score ??\n Number.MAX_SAFE_INTEGER,\n ),\n );\n const bScore = Math.min(\n ...b.tokens.map(\n (token) =>\n getTokenSearchRank(token, query)?.score ??\n Number.MAX_SAFE_INTEGER,\n ),\n );\n if (aScore !== bScore) return aScore - bScore;\n }\n return b.totalFiat - a.totalFiat;\n });\n }, [\n filtered,\n allowUnified,\n isTokenSelectedForVisibility,\n isUnifiedSelectedForVisibility,\n query,\n ]);\n\n const [expandedGroups, setExpandedGroups] = useState>(new Set());\n\n const toggleGroup = (symbol: string, e: React.MouseEvent) => {\n e.stopPropagation();\n setExpandedGroups((prev) => {\n const next = new Set(prev);\n if (next.has(symbol)) next.delete(symbol);\n else next.add(symbol);\n return next;\n });\n };\n\n const isTokenSelectedInOtherSlot = (token: SwapTokenOption) =>\n !allowSelectedTokenRemoval &&\n activeSelectedTokens.some(\n (st, idx) => idx !== editingAssetIndex && sameTokenOption(st, token),\n );\n\n const isTokenSelectedInCurrentSlot = (token: SwapTokenOption) => {\n if (isMulti) {\n return activeSelectedTokens.some(\n (st) =>\n sameTokenOption(st, token) ||\n Boolean(\n st.isUnified &&\n st.sourceTokens?.some((source) => sameTokenOption(source, token)),\n ),\n );\n }\n if (allowSelectedTokenRemoval) {\n return activeSelectedTokens.some(\n (st) =>\n sameTokenOption(st, token) ||\n Boolean(\n st.isUnified &&\n st.sourceTokens?.some((source) => sameTokenOption(source, token)),\n ),\n );\n }\n if (editingAssetIndex === null) return false;\n const st = activeSelectedTokens[editingAssetIndex];\n return sameTokenOption(st, token);\n };\n\n const isGroupUnifiedSelectedInOtherSlot = (\n group: (typeof groupedFiltered)[0],\n ) => {\n if (allowSelectedTokenRemoval) return false;\n const relevantTokens = isMulti\n ? activeSelectedTokens\n : activeSelectedTokens.filter((_, idx) => idx !== editingAssetIndex);\n return relevantTokens.some(\n (st) => st.isUnified && st.unifiedSymbol === group.symbol,\n );\n };\n\n const isGroupUnifiedSelectedInCurrentSlot = (\n group: (typeof groupedFiltered)[0],\n ) => {\n if (isMulti) {\n return activeSelectedTokens.some(\n (st) => st.isUnified && st.unifiedSymbol === group.symbol,\n );\n }\n if (editingAssetIndex === null) return false;\n const st = activeSelectedTokens[editingAssetIndex];\n return Boolean(st?.isUnified && st.unifiedSymbol === group.symbol);\n };\n\n const isAnyTokenInGroupSelectedInOtherSlot = (\n group: (typeof groupedFiltered)[0],\n ) => {\n if (allowSelectedTokenRemoval) return false;\n const relevantTokens = isMulti\n ? activeSelectedTokens\n : activeSelectedTokens.filter((_, idx) => idx !== editingAssetIndex);\n return relevantTokens.some(\n (st) =>\n group.tokens.some((gt) => sameTokenOption(gt, st)) ||\n (st.isUnified && st.unifiedSymbol === group.symbol),\n );\n };\n\n const selectorRows = useMemo(() => {\n if (isMulti) {\n return groupedFiltered.map((group) => ({\n fiat: group.totalFiat,\n group,\n key: `group:${group.symbol}`,\n kind: \"group\" as const,\n label: group.symbol,\n searchScore: query.trim()\n ? Math.min(\n ...group.tokens.map(\n (token) =>\n getTokenSearchRank(token, query)?.score ??\n Number.MAX_SAFE_INTEGER,\n ),\n )\n : 0,\n }));\n }\n\n const rows: Array<\n | {\n fiat: number;\n group: (typeof groupedFiltered)[number];\n key: string;\n kind: \"group\";\n label: string;\n searchScore: number;\n }\n | {\n fiat: number;\n key: string;\n kind: \"token\";\n label: string;\n searchScore: number;\n token: SwapTokenOption;\n }\n > = [];\n const hasQuery = Boolean(query.trim());\n const getSearchScore = (token: SwapTokenOption) =>\n hasQuery\n ? (getTokenSearchRank(token, query)?.score ?? Number.MAX_SAFE_INTEGER)\n : 0;\n const isVisibleTokenRow = (token: SwapTokenOption) =>\n showBelowMinimumInline ||\n getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(token) ||\n isPrioritySearchMatch(token, query);\n\n for (const group of groupedFiltered) {\n if (!group.isUnifiedCandidate) {\n for (const token of group.tokens) {\n if (!isVisibleTokenRow(token)) continue;\n rows.push({\n fiat: getTokenFiatValue(token),\n key: `token:${token.chainId}:${token.contractAddress}`,\n kind: \"token\",\n label: `${token.symbol} ${token.chainName}`,\n searchScore: getSearchScore(token),\n token,\n });\n }\n continue;\n }\n\n const unifiedSelectedInOther = isGroupUnifiedSelectedInOtherSlot(group);\n const unifiedSelectedInCurrent =\n isGroupUnifiedSelectedInCurrentSlot(group);\n const anyIndividualSelectedInOther =\n isAnyTokenInGroupSelectedInOtherSlot(group);\n const anyIndividualSelectedInCurrent = group.tokens.some(\n isTokenSelectedInCurrentSlot,\n );\n const shouldHideUnifiedRow =\n anyIndividualSelectedInOther ||\n anyIndividualSelectedInCurrent ||\n (group.totalFiat < MIN_FIAT_THRESHOLD &&\n !isUnifiedSelectedForVisibility(group.symbol));\n const shouldHideIndividualRows =\n unifiedSelectedInOther || unifiedSelectedInCurrent;\n\n if (!unifiedSelectedInOther && !shouldHideUnifiedRow) {\n rows.push({\n fiat: group.totalFiat,\n group,\n key: `group:${group.symbol}`,\n kind: \"group\",\n label: group.symbol,\n searchScore: hasQuery\n ? Math.min(\n ...group.tokens.map(\n (token) =>\n getTokenSearchRank(token, query)?.score ??\n Number.MAX_SAFE_INTEGER,\n ),\n )\n : 0,\n });\n }\n\n if (!shouldHideIndividualRows) {\n for (const token of group.tokens) {\n if (!isVisibleTokenRow(token)) continue;\n rows.push({\n fiat: getTokenFiatValue(token),\n key: `token:${token.chainId}:${token.contractAddress}`,\n kind: \"token\",\n label: `${token.symbol} ${token.chainName}`,\n searchScore: getSearchScore(token),\n token,\n });\n }\n }\n }\n\n return rows.sort((a, b) => {\n if (hasQuery && a.searchScore !== b.searchScore) {\n return a.searchScore - b.searchScore;\n }\n if (a.fiat !== b.fiat) return b.fiat - a.fiat;\n if (a.kind !== b.kind) return a.kind === \"group\" ? -1 : 1;\n return a.label.localeCompare(b.label);\n });\n }, [\n groupedFiltered,\n isMulti,\n isGroupUnifiedSelectedInCurrentSlot,\n isGroupUnifiedSelectedInOtherSlot,\n isAnyTokenInGroupSelectedInOtherSlot,\n isTokenSelectedInCurrentSlot,\n isTokenSelectedForVisibility,\n isUnifiedSelectedForVisibility,\n query,\n showBelowMinimumInline,\n ]);\n\n const handleFilterTabClick = (\n tab: FilterTab,\n chainId = selectedChainFilter,\n ) => {\n setActiveTab(tab);\n if (!autoSelectFilterTabs || !isMulti) return;\n if (tab === \"custom\") {\n onFilterTabSelect?.(tab);\n return;\n }\n if (\n onFilterTabSelect &&\n (tab === \"all\" || filterTabBehavior === \"source-pool\" || chainId !== null)\n ) {\n // A chain-scoped selection must not reuse the all-chain quote's sources.\n onFilterTabSelect(\n tab,\n chainId === null ? undefined : getFilterTabTokens(tab, chainId),\n );\n return;\n }\n if (onSelectionChange)\n emitSelectionChange(getFilterTabTokens(tab, chainId), tab);\n };\n\n const handleChainFilterChange = (chainId: number | null) => {\n setSelectedChainFilter(chainId);\n if (activeTab !== \"custom\") handleFilterTabClick(activeTab, chainId);\n closeChainSelector();\n };\n\n const getEditedSelectionTab = (): FilterTab =>\n activeTab === \"native\" || activeTab === \"stables\" ? activeTab : \"custom\";\n\n const handleClearSelection = () => {\n if (isMulti && onSelectionChange) {\n const tab = getEditedSelectionTab();\n setActiveTab(tab);\n emitSelectionChange([], tab);\n return;\n }\n onClearSelection?.();\n };\n\n const handleMultiTokenToggle = (token: SwapTokenOption) => {\n if (!autoSelectFilterTabs || !isMulti || !onSelectionChange) {\n onToggle?.(token);\n return;\n }\n\n pendingSelectionScrollTopRef.current = listRef.current?.scrollTop ?? null;\n skipNextSelectionScrollResetRef.current = true;\n const tab = getEditedSelectionTab();\n setActiveTab(tab);\n const current = mergeTokenOptions(\n activeSelectedTokens,\n lockedSelectedTokens,\n );\n const targets =\n token.isUnified && token.sourceTokens?.length\n ? token.sourceTokens\n : [token];\n const unlockedTargets = targets.filter((target) => !isLockedToken(target));\n if (unlockedTargets.length === 0) return;\n\n const allTargetsSelected = unlockedTargets.every((target) =>\n current.some((item) => sameTokenOption(item, target)),\n );\n const next = allTargetsSelected\n ? removeTokenOptions(current, unlockedTargets)\n : mergeTokenOptions(current, unlockedTargets);\n emitSelectionChange(next, tab);\n };\n\n /* ── Render a single-chain token row ── */\n const renderTokenRow = (\n token: SwapTokenOption,\n indent = false,\n isDisabledByUnified = false,\n ) => {\n const selectedInOther = !isMulti && isTokenSelectedInOtherSlot(token);\n if (selectedInOther) return null;\n\n const selectedInCurrent = isTokenSelectedInCurrentSlot(token);\n const locked = isLockedToken(token);\n const disabled = isDisabledByUnified || locked;\n return (\n {\n if (disabled) return;\n if (isMulti) {\n handleMultiTokenToggle(token);\n } else if (\n allowSelectedTokenRemoval &&\n selectedInCurrent &&\n onToggle\n ) {\n onToggle(token);\n } else onSelect(token);\n }}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"10px 14px\",\n paddingLeft: indent ? \"36px\" : \"14px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n borderBottom: \"1px solid var(--nexus-widget-surface-raised, #F0F0EF)\",\n boxSizing: \"border-box\",\n opacity: isDisabledByUnified ? 0.5 : 1,\n }}\n >\n
\n \n
\n \n
\n \n \n {token.symbol}\n \n {token.chainName && (\n
\n \n \n {token.chainName}\n \n
\n )}\n
\n \n \n \n {formatBalanceWithSymbol(token)}\n \n \n ≈ {token.balanceInFiat}\n \n \n \n );\n };\n\n /* ── Render a unified (multi-chain) group row ── */\n const renderGroupRow = (\n group: (typeof groupedFiltered)[0],\n includeIndividualRows = true,\n ) => {\n if (!group.isUnifiedCandidate) {\n return group.tokens\n .filter(\n (token) =>\n getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(token) ||\n isPrioritySearchMatch(token, query),\n )\n .map((token) => renderTokenRow(token));\n }\n\n const unifiedSelectedInOther =\n !isMulti && isGroupUnifiedSelectedInOtherSlot(group);\n if (unifiedSelectedInOther) return null;\n\n const individualTokens = group.tokens.filter(\n (token) =>\n getTokenFiatValue(token) >= MIN_FIAT_THRESHOLD ||\n isTokenSelectedForVisibility(token) ||\n isPrioritySearchMatch(token, query),\n );\n const hasVisibleUnifiedRow =\n (group.totalFiat >= MIN_FIAT_THRESHOLD ||\n isUnifiedSelectedForVisibility(group.symbol)) &&\n !unifiedSelectedInOther;\n const visibleTokensCount = individualTokens.filter(\n (t) => !isTokenSelectedInOtherSlot(t),\n ).length;\n if (!hasVisibleUnifiedRow && visibleTokensCount === 0) return null;\n\n const isExpanded = expandedGroups.has(group.symbol);\n const unifiedSelectedInCurrent = isGroupUnifiedSelectedInCurrentSlot(group);\n const anyIndividualSelectedInOther =\n isAnyTokenInGroupSelectedInOtherSlot(group);\n const anyIndividualSelectedInCurrent = group.tokens.some(\n isTokenSelectedInCurrentSlot,\n );\n const selectedChildCount = group.tokens.filter(\n isTokenSelectedInCurrentSlot,\n ).length;\n const areAllChildrenSelected =\n group.tokens.length > 0 && selectedChildCount === group.tokens.length;\n const isPartiallySelected =\n selectedChildCount > 0 && selectedChildCount < group.tokens.length;\n const shouldHideUnifiedRow =\n !isMulti &&\n (anyIndividualSelectedInOther ||\n anyIndividualSelectedInCurrent ||\n (group.totalFiat < MIN_FIAT_THRESHOLD &&\n !isUnifiedSelectedForVisibility(group.symbol)));\n const shouldHideIndividualRows =\n !isMulti && (unifiedSelectedInOther || unifiedSelectedInCurrent);\n const unifiedToken: SwapTokenOption = {\n ...group.tokens[0],\n balance: String(group.totalBalRaw),\n balanceInFiat: group.totalFiatStr,\n chainId: undefined,\n chainName: \"All Chains\",\n chainLogo: \"/nexus-widget/all-chains.png\",\n contractAddress: `${group.symbol}-UNIFIED`,\n isUnified: true,\n name: group.symbol,\n sourceTokens: group.tokens,\n symbol: group.symbol,\n unifiedSymbol: group.symbol as \"USDC\" | \"USDT\" | \"ETH\",\n };\n\n return (\n \n {!shouldHideUnifiedRow && (\n {\n if (isMulti) {\n toggleGroup(group.symbol, e);\n return;\n }\n onSelect(unifiedToken);\n }}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"10px 14px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n borderBottom:\n \"1px solid var(--nexus-widget-surface-raised, #F0F0EF)\",\n boxSizing: \"border-box\",\n }}\n >\n
\n {\n e.stopPropagation();\n if (isMulti) handleMultiTokenToggle(unifiedToken);\n else onSelect(unifiedToken);\n }}\n style={{ cursor: \"pointer\" }}\n >\n \n
\n \n \n \n \n
\n \n {group.symbol}\n \n \n UNIFIED\n \n
\n \n \n \n
\n \n \n {group.totalBalStr}\n \n \n ≈ {group.totalFiatStr}\n \n
\n \n \n )}\n {isMulti ? (\n \n
\n {group.tokens.map((token) => renderTokenRow(token, true, false))}\n
\n \n ) : (\n includeIndividualRows &&\n !shouldHideIndividualRows &&\n individualTokens.map((token) => renderTokenRow(token))\n )}\n \n );\n };\n\n const isLoading = !staticOptions && swapBalance === null;\n const selectedAssetCount = activeSelectedTokens.length;\n const requiredUsdAmount = parseTokenAmount(requiredUsd);\n const shouldCountSelectedUsd = (token: SwapTokenOption, value: Decimal) =>\n value.gt(0) && (isLockedToken(token) || value.gte(MIN_FIAT_THRESHOLD));\n const selectedUsdAmount = activeSelectedTokens.reduce((sum, token) => {\n if (token.isUnified && token.sourceTokens?.length) {\n return sum.plus(\n token.sourceTokens.reduce((sourceSum, source) => {\n const value =\n parseTokenAmount(source.balanceInFiat) ?? new Decimal(0);\n return shouldCountSelectedUsd(source, value)\n ? sourceSum.plus(value)\n : sourceSum;\n }, new Decimal(0)),\n );\n }\n const value = parseTokenAmount(token.balanceInFiat) ?? new Decimal(0);\n return shouldCountSelectedUsd(token, value) ? sum.plus(value) : sum;\n }, new Decimal(0));\n const selectionDeficitUsdAmount =\n requiredUsdAmount && selectedUsdAmount.lt(requiredUsdAmount)\n ? requiredUsdAmount.minus(selectedUsdAmount)\n : new Decimal(0);\n const hasSelectionShortfall = Boolean(\n requiredUsdAmount &&\n requiredUsdAmount.gt(0) &&\n selectionDeficitUsdAmount.gt(0),\n );\n const shouldShowSelectionProgress = Boolean(isMulti && hasSelectionShortfall);\n const selectionProgressPercent =\n shouldShowSelectionProgress && requiredUsdAmount\n ? Decimal.min(\n 100,\n selectedUsdAmount.div(requiredUsdAmount).mul(100),\n ).toNumber()\n : 0;\n const subtitle = isMulti\n ? `${selectedAssetCount} asset${selectedAssetCount === 1 ? \"\" : \"s\"} selected`\n : \"\";\n\n useEffect(() => {\n setPortalRoot(\n selectorRef.current?.closest(\n \"[data-nexus-widget-root]\",\n ) as HTMLElement | null,\n );\n }, []);\n\n useEffect(() => {\n return () => {\n if (chainCloseTimerRef.current) {\n clearTimeout(chainCloseTimerRef.current);\n }\n };\n }, []);\n\n const openChainSelector = () => {\n if (chainCloseTimerRef.current) {\n clearTimeout(chainCloseTimerRef.current);\n chainCloseTimerRef.current = null;\n }\n setChainQuery(\"\");\n setIsChainSelectorClosing(false);\n setShowChainSelector(true);\n };\n\n const closeChainSelector = () => {\n if (chainCloseTimerRef.current) {\n clearTimeout(chainCloseTimerRef.current);\n }\n setIsChainSelectorClosing(true);\n chainCloseTimerRef.current = setTimeout(() => {\n setShowChainSelector(false);\n setIsChainSelectorClosing(false);\n chainCloseTimerRef.current = null;\n }, CHAIN_SELECTOR_CLOSE_MS);\n };\n\n const chainOptions = useMemo(() => {\n const options = new Map();\n\n for (const chain of swapSupportedChains ?? []) {\n if (\n !sdkSwapSupportedChainIds &&\n !SWAP_CHAIN_DISPLAY_ORDER_SET.has(chain.id)\n ) {\n continue;\n }\n if (!isSwapSupportedBySdkChainList(chain.id, swapSupportedChains)) {\n continue;\n }\n options.set(chain.id, {\n contractAddress: \"\",\n symbol: \"\",\n name: getShortChainName(chain.id, chain.name),\n decimals: 18,\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n chainId: chain.id,\n chainName: getShortChainName(chain.id, chain.name),\n chainLogo: CHAIN_METADATA[chain.id]?.logo ?? chain.logo,\n });\n }\n\n for (const token of allTokens) {\n if (\n !token.chainId ||\n (!sdkSwapSupportedChainIds &&\n !SWAP_CHAIN_DISPLAY_ORDER_SET.has(token.chainId)) ||\n !isSwapSupportedBySdkChainList(token.chainId, swapSupportedChains)\n ) {\n continue;\n }\n if (!options.has(token.chainId)) {\n options.set(token.chainId, token);\n }\n }\n\n return Array.from(options.values()).sort(compareChainsBySwapDisplayOrder);\n }, [allTokens, sdkSwapSupportedChainIds, swapSupportedChains]);\n\n const selectedChainToken =\n selectedChainFilter === null\n ? undefined\n : chainOptions.find((token) => token.chainId === selectedChainFilter);\n const selectedChainLabel =\n selectedChainFilter === null\n ? \"All chains\"\n : selectedChainToken?.chainName || \"Chain\";\n\n const handleAutoSelectTokens = () => {\n handleFilterTabClick(\"all\");\n };\n\n const handleSelectManually = () => {\n handleFilterTabClick(\"custom\");\n };\n\n const handleDone = () => {\n if (hasSelectionShortfall) return;\n onDone?.(\n isMulti\n ? mergeTokenOptions(draftSelectedTokens, lockedSelectedTokens)\n : undefined,\n );\n };\n\n return (\n \n {/* Drawer Handle */}\n \n \n \n\n {/* Header */}\n \n \n \n \n \n \n {title}\n \n {subtitle && (\n \n {subtitle}\n \n )}\n \n {isMulti &&\n selectedAssetCount > 0 &&\n (onClearSelection || onSelectionChange) && (\n \n Deselect all\n \n )}\n \n\n {/* Search */}\n
\n \n \n setIsSearchFocused(false)}\n onChange={(e) => setQuery(e.target.value)}\n onFocus={() => setIsSearchFocused(true)}\n placeholder=\"Search token, chain or address\"\n style={{\n flex: 1,\n backgroundColor: \"transparent\",\n border: \"none\",\n outline: \"none\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: 14,\n color: \"var(--nexus-widget-text-strong, #161615)\",\n minWidth: 0,\n }}\n value={query}\n />\n {query && (\n setQuery(\"\")}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: 0,\n }}\n >\n \n \n )}\n {/* Chain Selector Badge */}\n \n {selectedChainFilter === null ? (\n \n ) : (\n \n )}\n \n {selectedChainLabel}\n \n \n \n
\n \n\n {/* Filter tabs */}\n \n {visibleFilterTabs.map((tab) => (\n handleFilterTabClick(tab.key)}\n style={{\n flex: 1,\n padding: \"6px 0\",\n backgroundColor:\n activeTab === tab.key\n ? \"var(--nexus-widget-surface-active, #FFFFFE)\"\n : \"transparent\",\n border: \"none\",\n borderRadius: 6,\n cursor: \"pointer\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: 13,\n fontWeight: 500,\n color:\n activeTab === tab.key\n ? \"var(--nexus-widget-text-strong, #161615)\"\n : \"var(--nexus-widget-text-secondary, #848483)\",\n boxShadow:\n activeTab === tab.key\n ? \"0px 1px 2px var(--nexus-widget-shadow-soft, rgba(0,0,0,0.05))\"\n : \"none\",\n transition: \"all 0.15s\",\n }}\n >\n {autoSelectFilterTabs && tab.key === \"all\"\n ? \"Any token\"\n : tab.label}\n \n ))}\n \n\n {/* Token list */}\n \n {isLoading ? (\n \n \n \n Loading assets…\n

\n \n ) : aboveMin.length === 0 && belowMin.length === 0 ? (\n \n No tokens found\n

\n ) : (\n
\n {groupedFiltered.length > 0 && (\n \n {selectorRows.map((row) =>\n row.kind === \"group\"\n ? renderGroupRow(row.group, isMulti)\n : renderTokenRow(row.token),\n )}\n
\n )}\n\n {belowMin.length > 0 && (\n \n setShowBelowMin((v) => !v)}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"11px 12px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n boxSizing: \"border-box\",\n }}\n >\n \n \n \n \n \n \n Tokens below minimum\n \n \n {showBelowMin\n ? \"Tokens under $1 are unavailable for swaps\"\n : \"Hidden to prevent failed swaps\"}\n \n \n \n \n {/* Small token logo cluster */}\n
\n {belowMin.slice(0, 3).map((t, i) => (\n 0 ? -6 : 0,\n }}\n />\n ))}\n {belowMin.length > 3 && (\n \n +{belowMin.length - 3}\n
\n )}\n \n {showBelowMin ? (\n \n ) : (\n \n )}\n \n \n \n
\n {belowMin.map((token, index) => (\n \n \n \n \n {token.chainLogo && (\n \n )}\n
\n \n {token.symbol} on{\" \"}\n {token.chainName || \"Unknown chain\"}\n \n \n \n {token.balanceInFiat}\n \n \n ))}\n \n \n \n )}\n \n )}\n \n\n {/* Done button */}\n {isMulti && (\n
\n {shouldShowSelectionProgress && requiredUsdAmount && (\n \n {autoSelectFilterTabs && hasSelectionShortfall && (\n \n \n {selectedChainFilter !== null\n ? \"Your selection doesn't cover the full amount\"\n : activeTab === \"all\"\n ? \"You don't have enough balances to meet this requirement\"\n : activeTab === \"native\"\n ? \"Your native tokens don't cover the full amount\"\n : activeTab === \"stables\"\n ? \"Your stablecoins don't cover the full amount\"\n : \"Your selection doesn't cover the full amount\"}\n \n \n {selectedChainFilter !== null\n ? \"Switch to “All chains” to include more tokens.\"\n : activeTab === \"all\"\n ? \"Add more tokens to your wallet\"\n : `${formatUsdBalanceLabel(selectionDeficitUsdAmount)} more is needed.`}\n \n {(activeTab === \"native\" || activeTab === \"stables\") && (\n \n \n Auto-select tokens\n \n \n Select manually\n \n
\n )}\n \n )}\n \n \n \n Required\n \n \n \n {formatUsdBalanceLabel(selectionDeficitUsdAmount)}\n {\" \"}\n more\n \n \n \n \n \n \n \n )}\n {!hasSelectionShortfall && (\n \n Done\n \n )}\n \n )}\n\n {/* Chain Selector Modal */}\n {showChainSelector &&\n (() => {\n const chainModal = (\n \n \n \n \n \n \n \n \n \n \n \n Select chain\n \n \n\n {/* Search */}\n
\n \n \n setIsChainSearchFocused(false)}\n onChange={(e) => setChainQuery(e.target.value)}\n onFocus={() => setIsChainSearchFocused(true)}\n placeholder=\"Search chains\"\n style={{\n flex: 1,\n backgroundColor: \"transparent\",\n border: \"none\",\n outline: \"none\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: 13,\n color: \"var(--nexus-widget-text-strong, #161615)\",\n }}\n value={chainQuery}\n />\n
\n \n\n {/* Chain list */}\n \n \n {\n handleChainFilterChange(null);\n }}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px 14px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n borderBottom:\n \"1px solid var(--nexus-widget-surface-raised, #F0F0EF)\",\n cursor: \"pointer\",\n boxSizing: \"border-box\",\n }}\n >\n \n \n \n All Chains\n \n \n\n {/* Unique chains */}\n {chainOptions\n .filter((t) =>\n (t.chainName || \"\")\n .toLowerCase()\n .includes(chainQuery.toLowerCase()),\n )\n .map((t) => (\n {\n handleChainFilterChange(t.chainId!);\n }}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px 14px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n borderBottom:\n \"1px solid var(--nexus-widget-surface-raised, #F0F0EF)\",\n cursor: \"pointer\",\n boxSizing: \"border-box\",\n }}\n >\n \n \n \n {t.chainName}\n \n \n ))}\n \n \n \n \n );\n return portalRoot ? createPortal(chainModal, portalRoot) : chainModal;\n })()}\n \n );\n}\n", "type": "registry:component", "target": "components/nexus/components/swap-asset-selector.tsx" }, { "path": "registry/avail-widgets/nexus-widget/components/swap-idle-form.tsx", - "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport Decimal from \"decimal.js\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport { useNexusWidgetThemeStyle } from \"../theme-context\";\nimport {\n formatSelectedTokenBalanceLabel,\n formatUsdBalanceLabel,\n type SwapTokenOption,\n} from \"./swap-asset-selector\";\n\nconst tabularNums: React.CSSProperties = {\n fontFeatureSettings: '\"tnum\"',\n fontVariantNumeric: \"tabular-nums\",\n};\n\nconst brand = \"var(--foreground-brand)\";\n\ninterface SwapIdleFormProps {\n amount: string;\n defaultRecipientAddress?: string;\n fromTokens: SwapTokenOption[];\n isAmountReadOnly?: boolean;\n isBalanceLoading?: boolean;\n isDestinationPickerDisabled?: boolean;\n hideDestinationTokenDropdownIcon?: boolean;\n isReceiveAmountLoading?: boolean;\n isReceiveUsdLoading?: boolean;\n isSourcePickerDisabled?: boolean;\n onAmountChange: (val: string, panel: \"send\" | \"receive\") => void;\n onOpenDestPicker: () => void;\n onOpenRecipientPicker?: () => void;\n onOpenSourcePicker: (index?: number) => void;\n onUpdateTokens?: (tokens: SwapTokenOption[]) => void;\n receiveQuoteAmount?: string;\n receiveQuoteUsd?: string;\n recipientAddress?: string;\n sourceRouteMessage?: string;\n sourceRouteStatus?: \"loading\" | \"insufficient\";\n swapType: \"exactIn\" | \"exactOut\";\n toToken?: SwapTokenOption;\n totalBalance: string;\n usdValue: string;\n}\n\n/** Chevron down icon used in asset selector pills */\nconst ChevronDownIcon = () => (\n \n \n \n);\n\nconst ArrowUpDownIcon = () => (\n \n \n \n);\n\n/** Reusable percentage quick-select buttons row with transition wrapper */\nfunction PercentButtons({\n visible,\n onSelect,\n maxLabel = \"Max\",\n token,\n}: {\n visible: boolean;\n onSelect: (pct: number) => void;\n maxLabel?: string;\n token: SwapTokenOption;\n}) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [hoveredPct, setHoveredPct] = useState(null);\n const isUsdMode = token.userAmountMode === \"usd\";\n const balance = parseDecimal(isUsdMode ? token.balanceInFiat : token.balance);\n const enteredAmount = parseDecimal(token.userAmount);\n const decimals = isUsdMode ? MAX_AMOUNT_DISPLAY_DECIMALS : getTokenInputDecimals(token);\n\n return (\n \n {[20, 50, 100].map((pct) => {\n const label = pct === 100 ? maxLabel : `${pct}%`;\n const isHovered = hoveredPct === pct;\n const isSelected = Boolean(\n balance?.gt(0) && enteredAmount?.gt(0) &&\n enteredAmount.eq(balance.mul(pct).div(100).toDecimalPlaces(decimals, Decimal.ROUND_DOWN))\n );\n\n return (\n {\n e.stopPropagation();\n onSelect(pct);\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n }}\n onMouseEnter={() => setHoveredPct(pct)}\n onMouseLeave={() => setHoveredPct(null)}\n style={{\n alignItems: \"center\",\n backgroundColor: isHovered ? \"var(--nexus-widget-surface, #FFFFFF)\" : \"transparent\",\n borderRadius: \"4px\",\n boxShadow: isHovered ? \"var(--nexus-widget-shadow-soft, #3C286414) 0px 1px 2px\" : \"none\",\n boxSizing: \"border-box\",\n color: isHovered ? \"var(--nexus-widget-text, #1F1F1F)\" : \"var(--nexus-widget-text-secondary, #8E8E89)\",\n cursor: \"pointer\",\n display: \"flex\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"10px\",\n fontWeight: 500,\n height: \"18px\",\n justifyContent: \"center\",\n flex: \"1 1 0%\",\n minWidth: 0,\n paddingInline: \"3px\",\n border: \"none\",\n transition: \"all 0.15s ease-out\",\n }}\n tabIndex={-1}\n type=\"button\"\n >\n {label}\n \n );\n })}\n \n );\n}\n\nfunction UnifiedTokenLogoBadge({\n token,\n size = 24,\n}: {\n token: SwapTokenOption;\n size?: number;\n}) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [popover, setPopover] = useState<{\n left: number;\n top: number;\n width: number;\n maxHeight: number;\n } | null>(null);\n const triggerRef = useRef(null);\n const sources = token.sourceTokens ?? [];\n const chainCount =\n new Set(\n sources\n .map((source) => source.chainId ?? source.chainName)\n .filter(Boolean),\n ).size || sources.length;\n\n const showPopover = () => {\n const rect = triggerRef.current?.getBoundingClientRect();\n if (!rect || typeof window === \"undefined\") return;\n const width = 250;\n const maxHeight = 260;\n const viewportPadding = 8;\n const left = Math.min(\n Math.max(viewportPadding, rect.right - width),\n window.innerWidth - width - viewportPadding,\n );\n const belowTop = rect.bottom + 8;\n const top =\n belowTop + maxHeight > window.innerHeight\n ? Math.max(viewportPadding, rect.top - maxHeight - 8)\n : belowTop;\n setPopover({ left, top, width, maxHeight });\n };\n\n return (\n setPopover(null)}\n ref={triggerRef}\n style={{\n boxSizing: \"border-box\",\n flexShrink: 0,\n height: `${size}px`,\n position: \"relative\",\n width: `${size}px`,\n }}\n >\n \n {chainCount > 0 && (\n 9 ? \"3px\" : 0,\n position: \"absolute\",\n right: -3,\n }}\n >\n {chainCount}\n \n )}\n {popover &&\n sources.length > 0 &&\n typeof document !== \"undefined\" &&\n createPortal(\n \n \n \n Unified · {chainCount} {chainCount === 1 ? \"Chain\" : \"Chains\"}\n \n \n ≈ {formatUsdBalanceLabel(token.balanceInFiat)}\n \n \n \n {sources.map((source) => (\n \n \n \n \n {source.chainName || \"Unknown chain\"}\n \n \n \n {formatAmountInputDisplay(source.balance || \"0\")}\n \n \n ))}\n \n ,\n document.body,\n )}\n \n );\n}\n\nfunction PercentHoverButton({\n label,\n onClick,\n tabIndex,\n}: {\n label: string;\n onClick: () => void;\n tabIndex?: number;\n}) {\n const [hover, setHover] = useState(false);\n const [active, setActive] = useState(false);\n const handledPointerDownRef = useRef(false);\n const pointerResetTimerRef = useRef | null>(\n null,\n );\n\n useEffect(() => {\n return () => {\n if (pointerResetTimerRef.current) {\n clearTimeout(pointerResetTimerRef.current);\n }\n };\n }, []);\n\n const isHighlighted = hover || active;\n\n return (\n {\n if (handledPointerDownRef.current) {\n if (pointerResetTimerRef.current) {\n clearTimeout(pointerResetTimerRef.current);\n pointerResetTimerRef.current = null;\n }\n handledPointerDownRef.current = false;\n return;\n }\n onClick();\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n setActive(true);\n }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => {\n setHover(false);\n setActive(false);\n }}\n onMouseUp={() => setActive(false)}\n onPointerDown={(event) => {\n if (event.pointerType === \"mouse\") return;\n event.preventDefault();\n if (pointerResetTimerRef.current) {\n clearTimeout(pointerResetTimerRef.current);\n }\n handledPointerDownRef.current = true;\n setActive(true);\n onClick();\n }}\n onPointerUp={() => {\n setActive(false);\n if (handledPointerDownRef.current) {\n pointerResetTimerRef.current = setTimeout(() => {\n handledPointerDownRef.current = false;\n pointerResetTimerRef.current = null;\n }, 350);\n }\n }}\n style={{\n alignItems: \"center\",\n backgroundColor: isHighlighted ? \"var(--nexus-widget-primary-soft, #E8F0FF)\" : \"var(--nexus-widget-surface-raised, #F4F4F3)\",\n borderRadius: \"6px\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flex: \"1 1 0%\",\n justifyContent: \"center\",\n paddingBlock: \"3px\",\n paddingInline: \"6px\",\n border: \"none\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s ease-out\",\n }}\n tabIndex={tabIndex}\n >\n \n {label}\n \n \n );\n}\n\nfunction SkeletonBar({\n width,\n height,\n borderRadius = \"8px\",\n}: {\n width: string;\n height: string;\n borderRadius?: string;\n}) {\n return (\n \n );\n}\n\nfunction LogoCircle({\n src,\n alt,\n label,\n size,\n fontSize,\n outline,\n style,\n}: {\n src?: string;\n alt?: string;\n label?: string;\n size: number;\n fontSize: number;\n outline?: string;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n const fallbackLabel = (label || alt || \"?\").trim().slice(0, 1).toUpperCase();\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderRadius: \"999px\",\n height: `${size}px`,\n objectFit: \"cover\",\n outline,\n width: `${size}px`,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {fallbackLabel || \"?\"}\n \n );\n}\n\nconst sameAddress = (a?: string, b?: string) =>\n Boolean(a && b && a.toLowerCase() === b.toLowerCase());\n\nconst formatShortAddress = (address?: string) => {\n if (!address) return \"\";\n return address.length > 12\n ? `${address.slice(0, 6)}…${address.slice(-4)}`\n : address;\n};\n\nconst formatTokenBalanceLabel = formatSelectedTokenBalanceLabel;\n\nconst formatUsdValue = (value: Decimal) =>\n value.gt(0) && value.lt(0.01) ? \"<0.01\" : value.toDecimalPlaces(2).toFixed(2);\n\nconst MAX_AMOUNT_DISPLAY_DECIMALS = 8;\nconst getTokenInputDecimals = (token?: Pick) => {\n const decimals = Number(token?.decimals);\n return Number.isFinite(decimals) && decimals >= 0 ? Math.floor(decimals) : 18;\n};\n\nconst formatAmountInputDisplay = (value: string) => {\n if (!value) return \"\";\n try {\n return new Decimal(value)\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n } catch {\n return value;\n }\n};\n\nexport function SwapIdleForm({\n amount,\n receiveQuoteAmount,\n receiveQuoteUsd,\n isReceiveAmountLoading = false,\n isReceiveUsdLoading = false,\n sourceRouteStatus,\n sourceRouteMessage,\n onAmountChange,\n fromTokens,\n toToken,\n totalBalance,\n usdValue,\n onOpenSourcePicker,\n onOpenDestPicker,\n onOpenRecipientPicker,\n recipientAddress,\n defaultRecipientAddress,\n swapType,\n onUpdateTokens,\n isAmountReadOnly = false,\n isBalanceLoading = false,\n isDestinationPickerDisabled = false,\n hideDestinationTokenDropdownIcon = false,\n isSourcePickerDisabled = false,\n}: SwapIdleFormProps) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [focusedPanel, setFocusedPanel] = useState<\"send\" | \"receive\" | null>(\n null,\n );\n const [focusedRow, setFocusedRow] = useState(null);\n const [tooltip, setTooltip] = useState(null);\n const [tooltipTriggerRect, setTooltipTriggerRect] = useState(\n null,\n );\n const sourceListRef = useRef(null);\n const sourceRowRefs = useRef>({});\n const sourceInputRefs = useRef>({});\n const previousSourceCountRef = useRef(fromTokens.length);\n const prevTokensRef = useRef(fromTokens);\n const [autofocusIndex, setAutofocusIndex] = useState(null);\n\n useEffect(() => {\n const prev = prevTokensRef.current;\n if (fromTokens.length > prev.length) {\n setAutofocusIndex(fromTokens.length - 1);\n } else if (fromTokens.length === prev.length) {\n for (let i = 0; i < fromTokens.length; i++) {\n const p = prev[i];\n const c = fromTokens[i];\n if (\n p &&\n c &&\n (p.contractAddress !== c.contractAddress ||\n p.chainId !== c.chainId) &&\n !c.userAmount\n ) {\n setAutofocusIndex(i);\n break;\n }\n }\n }\n prevTokensRef.current = fromTokens;\n }, [fromTokens]);\n\n useEffect(() => {\n const previousSourceCount = previousSourceCountRef.current;\n if (fromTokens.length > previousSourceCount && previousSourceCount > 0) {\n const newIndex = fromTokens.length - 1;\n requestAnimationFrame(() => {\n const input = sourceInputRefs.current[newIndex];\n if (input) {\n input.focus();\n input.select();\n }\n\n const container = sourceListRef.current;\n const row = sourceRowRefs.current[newIndex];\n if (\n !container ||\n !row ||\n container.scrollHeight <= container.clientHeight\n ) {\n return;\n }\n\n const containerRect = container.getBoundingClientRect();\n const rowRect = row.getBoundingClientRect();\n const nextTop =\n rowRect.top - containerRect.top + container.scrollTop - 8;\n\n container.scrollTo({\n behavior: \"smooth\",\n top: Math.max(0, nextTop),\n });\n });\n }\n previousSourceCountRef.current = fromTokens.length;\n }, [fromTokens.length]);\n\n const sanitizeInput = (raw: string, maxDecimals = 18): string => {\n let next = raw.replaceAll(/[^0-9.]/g, \"\");\n const parts = next.split(\".\");\n if (parts.length > 2) next = parts[0] + \".\" + parts.slice(1).join(\"\");\n const [integerPart, decimalPart] = next.split(\".\");\n if (decimalPart !== undefined) {\n next = `${integerPart}.${decimalPart.slice(0, Math.max(0, maxDecimals))}`;\n }\n if (next === \".\") next = \"0.\";\n // Strip leading zeros\n if (next.length > 1 && next.startsWith(\"0\") && next[1] !== \".\") {\n next = next.replace(/^0+/, \"\");\n if (next === \"\") next = \"0\";\n if (next.startsWith(\".\")) next = \"0\" + next;\n }\n return next;\n };\n\n const handleBlurAmount = (index: number) => {\n if (!onUpdateTokens) return;\n const token = fromTokens[index];\n if (!token || !token.userAmount) return;\n if (token.userAmount.includes(\".\")) {\n const stripped = token.userAmount.replace(/0+$/, \"\").replace(/\\.$/, \"\");\n if (stripped !== token.userAmount) {\n const next = [...fromTokens];\n next[index] = { ...token, userAmount: stripped };\n onUpdateTokens(next);\n }\n }\n };\n\n const handleSendInput = (e: React.ChangeEvent) => {\n if (isAmountReadOnly) return;\n const token = fromTokens.length === 1 ? fromTokens[0] : undefined;\n onAmountChange(\n sanitizeInput(e.target.value, getTokenInputDecimals(token)),\n \"send\",\n );\n };\n\n const handleTokenAmountChange = (index: number, val: string) => {\n if (isAmountReadOnly) return;\n if (!onUpdateTokens) return;\n const token = fromTokens[index];\n if (!token) return;\n\n let sanitized = sanitizeInput(\n val,\n token.userAmountMode === \"usd\"\n ? MAX_AMOUNT_DISPLAY_DECIMALS\n : getTokenInputDecimals(token),\n );\n\n const next = [...fromTokens];\n next[index] = { ...token, userAmount: sanitized };\n onUpdateTokens(next);\n\n // Also update total amount for backwards compatibility if needed\n const total = next.reduce((sum, t) => sum + Number(t.userAmount || 0), 0);\n onAmountChange(total > 0 ? String(total) : \"\", \"send\");\n };\n\n const handleToggleMode = (index: number) => {\n if (isAmountReadOnly) return;\n if (!onUpdateTokens) return;\n const token = fromTokens[index];\n if (!token) return;\n\n const tokenBalance =\n parseDecimal(token.balance)?.toNumber() ?? 0;\n const fiatBalance =\n parseDecimal(token.balanceInFiat)?.toNumber() ?? 0;\n const price = tokenBalance > 0 ? fiatBalance / tokenBalance : 0;\n if (price === 0) return;\n\n const currentVal = Number(token.userAmount || 0);\n const next = [...fromTokens];\n if (token.userAmountMode === \"usd\") {\n const newTokenVal = currentVal > 0 ? (currentVal / price).toString() : \"\";\n next[index] = {\n ...token,\n userAmountMode: \"token\",\n userAmount: newTokenVal ? newTokenVal.substring(0, 10) : \"\",\n };\n } else {\n const newUsdVal = currentVal > 0 ? (currentVal * price).toFixed(2) : \"\";\n next[index] = { ...token, userAmountMode: \"usd\", userAmount: newUsdVal };\n }\n onUpdateTokens(next);\n const total = getTokenAmountTotal(next);\n onAmountChange(total > 0 ? String(total) : \"\", \"send\");\n };\n\n const getSourceUsdValue = React.useCallback((token: SwapTokenOption) => {\n if (!token || !token.userAmount) return 0;\n const quotedUsd = parseDecimal(token.userAmountUsd);\n if (quotedUsd && quotedUsd.gte(0)) return quotedUsd.toNumber();\n const tokenBalance =\n parseDecimal(token.balance)?.toNumber() ?? 0;\n const fiatBalance =\n parseDecimal(token.balanceInFiat)?.toNumber() ?? 0;\n const price = tokenBalance > 0 ? fiatBalance / tokenBalance : 0;\n const amountNumber = Number(token.userAmount || 0);\n if (!Number.isFinite(amountNumber)) return 0;\n if (token.userAmountMode === \"usd\") return amountNumber;\n return amountNumber * price;\n }, []);\n\n const totalUsd = React.useMemo(() => {\n return fromTokens.reduce((sum, token) => sum + getSourceUsdValue(token), 0);\n }, [fromTokens, getSourceUsdValue]);\n\n const hasSourceOverflow = fromTokens.length > 3;\n const [isSourceListAtBottom, setIsSourceListAtBottom] = useState(false);\n const updateSourceListScrollState = React.useCallback(() => {\n const element = sourceListRef.current;\n if (!element || !hasSourceOverflow) {\n setIsSourceListAtBottom(false);\n return;\n }\n\n const distanceFromBottom =\n element.scrollHeight - element.scrollTop - element.clientHeight;\n setIsSourceListAtBottom(distanceFromBottom <= 2);\n }, [hasSourceOverflow]);\n\n useEffect(() => {\n requestAnimationFrame(updateSourceListScrollState);\n }, [fromTokens.length, updateSourceListScrollState]);\n\n const sourceRowsToRender: Array<{\n token: SwapTokenOption | null;\n index: number;\n position: number;\n }> =\n fromTokens.length > 0\n ? fromTokens.map((token, index) => ({ token, index, position: index }))\n : [{ token: null, index: 0, position: 0 }];\n\n const isExactIn = swapType === \"exactIn\";\n const showSourceRouteSkeleton = !isExactIn && sourceRouteStatus === \"loading\";\n const sourceRouteHelper =\n sourceRouteStatus === \"insufficient\" ? sourceRouteMessage : undefined;\n const receiveBalanceLabel = formatTokenBalanceLabel(toToken);\n const getReceiveUsdRate = () => {\n const quoteTokenAmount = parseDecimal(receiveQuoteAmount);\n const quoteUsdAmount = parseDecimal(receiveQuoteUsd);\n if (quoteTokenAmount?.gt(0) && quoteUsdAmount?.gt(0)) {\n return quoteUsdAmount.div(quoteTokenAmount);\n }\n\n const tokenBalance = parseDecimal(toToken?.balance);\n const fiatBalance = parseDecimal(toToken?.balanceInFiat);\n if (tokenBalance?.gt(0) && fiatBalance?.gt(0)) {\n return fiatBalance.div(tokenBalance);\n }\n\n return undefined;\n };\n const receiveInputValue = isExactIn ? (receiveQuoteAmount ?? \"\") : amount;\n const receiveDisplayValue =\n focusedPanel === \"receive\"\n ? receiveInputValue\n : formatAmountInputDisplay(receiveInputValue);\n const receiveAmountTextColor =\n (!isExactIn && amount) || (isExactIn && receiveQuoteAmount)\n ? \"var(--nexus-widget-text-strong, #161615)\"\n : \"var(--nexus-widget-text-tertiary, #9E9E9C)\";\n const receiveUsdRate = getReceiveUsdRate();\n const receiveTokenAmount = parseDecimal(receiveInputValue);\n const receiveUsdAmount = receiveQuoteUsd\n ? parseDecimal(receiveQuoteUsd)\n : receiveTokenAmount && receiveUsdRate\n ? receiveTokenAmount.mul(receiveUsdRate)\n : undefined;\n const receiveAltValue = `≈ $${\n receiveUsdAmount ? formatUsdValue(receiveUsdAmount) : \"0.00\"\n }`;\n const isDefaultRecipient = sameAddress(\n recipientAddress,\n defaultRecipientAddress,\n );\n const recipientColor = recipientAddress\n ? isDefaultRecipient\n ? \"var(--nexus-widget-primary-soft-text, var(--foreground-brand))\"\n : \"var(--nexus-widget-warning-text, #B7791F)\"\n : \"var(--nexus-widget-text-secondary, #848483)\";\n const getTokenAmountTotal = (tokens: SwapTokenOption[]) =>\n tokens.reduce((sum, item) => sum + Number(item.userAmount || 0), 0);\n\n const handleSendPercentForToken = (\n index: number,\n pct: number,\n token: SwapTokenOption,\n ) => {\n if (isAmountReadOnly) return;\n if (!token.balance || !onUpdateTokens) return;\n let finalVal = \"\";\n const isUsdMode = token.userAmountMode === \"usd\";\n\n if (isUsdMode) {\n const fiatBalStr = String(token.balanceInFiat || \"0\");\n const fiatBalance = parseDecimal(fiatBalStr);\n if (!fiatBalance) return;\n if (pct === 100) {\n finalVal = fiatBalance\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n } else {\n finalVal = fiatBalance\n .mul(pct)\n .div(100)\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n }\n } else {\n const balanceStr = String(token.balance || \"0\");\n const tokenBalance = parseDecimal(balanceStr);\n if (!tokenBalance) return;\n const tokenDecimals = getTokenInputDecimals(token);\n if (pct === 100) {\n finalVal = tokenBalance\n .toDecimalPlaces(tokenDecimals, Decimal.ROUND_DOWN)\n .toFixed();\n } else {\n finalVal = tokenBalance\n .mul(pct)\n .div(100)\n .toDecimalPlaces(tokenDecimals, Decimal.ROUND_DOWN)\n .toFixed();\n }\n }\n\n const next = [...fromTokens];\n next[index] = {\n ...next[index],\n userAmount: finalVal,\n userAmountMode: isUsdMode ? \"usd\" : \"token\",\n };\n onUpdateTokens(next);\n const total = getTokenAmountTotal(next);\n onAmountChange(total > 0 ? String(total) : \"\", \"send\");\n };\n\n const handleSendPercent = (pct: number) => {\n if (isAmountReadOnly) return;\n if (!totalBalance) return;\n const bal = parseFloat(totalBalance.replace(/[^0-9.]/g, \"\"));\n if (isNaN(bal)) return;\n const val = bal * (pct / 100);\n // If there's only one token, or no tokens, update the main amount\n if (fromTokens.length <= 1) {\n if (fromTokens.length === 1 && onUpdateTokens) {\n handleSendPercentForToken(0, pct, fromTokens[0]);\n return;\n }\n onAmountChange(val.toFixed(6).replace(/\\.?0+$/, \"\"), \"send\");\n }\n };\n\n return (\n \n {(isReceiveAmountLoading || isReceiveUsdLoading || sourceRouteStatus) && (\n \n )}\n {/* ─── SEND PANEL ─── */}\n \n {/* Header row: SEND + add asset */}\n \n \n Send\n \n onOpenSourcePicker()}\n style={{\n alignItems: \"center\",\n background: \"transparent\",\n border: \"none\",\n borderRadius: \"6px\",\n display: \"flex\",\n gap: \"4px\",\n padding: \"2px 0\",\n color:\n fromTokens.length > 0 && !isSourcePickerDisabled\n ? \"var(--nexus-widget-primary-soft-text, var(--foreground-brand))\"\n : \"var(--nexus-widget-text-secondary, #A8A8A6)\",\n cursor:\n fromTokens.length > 0 && !isSourcePickerDisabled\n ? \"pointer\"\n : \"not-allowed\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"12px\",\n fontWeight: 500,\n lineHeight: \"18px\",\n opacity:\n fromTokens.length > 0 && !isSourcePickerDisabled ? 1 : 0.75,\n }}\n type=\"button\"\n >\n \n +\n \n Add more assets\n \n \n\n {/* Render each selected source asset, or an empty one if none */}\n \n {sourceRowsToRender.map(({ token, index, position }) => {\n const showTooltipBelow = position === 0;\n return (\n {\n sourceRowRefs.current[index] = element;\n }}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"5px\",\n opacity: 1,\n position: \"relative\",\n transform: \"translateY(0)\",\n transition: \"opacity 0.18s ease, transform 0.18s ease\",\n zIndex: tooltip === `asset-send-${index}` ? 1000 : 1,\n }}\n >\n \n \n {showSourceRouteSkeleton ? (\n \n ) : (\n <>\n {token?.userAmountMode === \"usd\" && (\n \n $\n \n )}\n {\n if (token) handleBlurAmount(index);\n setFocusedRow(null);\n }}\n onChange={(e) => {\n if (token)\n handleTokenAmountChange(index, e.target.value);\n else handleSendInput(e);\n }}\n onFocus={() => setFocusedRow(index)}\n placeholder=\"0\"\n ref={(element) => {\n sourceInputRefs.current[index] = element;\n }}\n style={{\n boxSizing: \"border-box\",\n color: (\n token\n ? Boolean(token.userAmount)\n : Boolean(isExactIn && amount)\n )\n ? \"var(--nexus-widget-text-strong, #161615)\"\n : \"var(--nexus-widget-text-tertiary, #9E9E9C)\",\n cursor: isAmountReadOnly ? \"default\" : \"text\",\n fontFamily:\n '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"29px\",\n fontWeight: 500,\n lineHeight: \"34px\",\n background: \"transparent\",\n border: \"none\",\n outline: \"none\",\n padding: 0,\n width: \"100%\",\n minWidth: 0,\n }}\n readOnly={isAmountReadOnly}\n type=\"text\"\n value={\n token\n ? focusedRow === index\n ? token.userAmount || \"\"\n : formatAmountInputDisplay(\n token.userAmount || \"\",\n )\n : isExactIn\n ? focusedRow === index\n ? amount\n : formatAmountInputDisplay(amount)\n : \"\"\n }\n />\n \n )}\n \n\n {/* Asset selector pill + cross button */}\n \n {showSourceRouteSkeleton ? (\n \n \n \n ) : (\n onOpenSourcePicker(index)}\n style={{\n alignItems: \"center\",\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderColor: token ? \"var(--nexus-widget-border, #E8E8E7)\" : \"var(--nexus-widget-border-empty, #C8C8C7)\",\n borderRadius: \"999px\",\n borderStyle: token ? \"solid\" : \"dashed\",\n borderWidth: \"1px\",\n boxShadow: token ? \"var(--nexus-widget-shadow-soft, #1616150A) 0px 1px 2px\" : \"none\",\n boxSizing: \"border-box\",\n display: \"flex\",\n gap: \"8px\",\n paddingBottom: \"5px\",\n paddingLeft: token ? \"5px\" : \"10px\",\n paddingRight: \"10px\",\n paddingTop: \"5px\",\n cursor: isSourcePickerDisabled\n ? \"not-allowed\"\n : \"pointer\",\n flexShrink: 0,\n opacity: isSourcePickerDisabled ? 0.72 : 1,\n }}\n >\n {token ? (\n token.isUnified ? (\n \n ) : (\n \n \n {token.chainLogo && (\n \n )}\n \n )\n ) : (\n \n )}\n \n {token ? token.symbol : \"Assets\"}\n \n \n \n )}\n {token && fromTokens.length > 1 && (\n {\n if (!onUpdateTokens) return;\n const next = [...fromTokens];\n next.splice(index, 1);\n onUpdateTokens(next);\n const total = getTokenAmountTotal(next);\n onAmountChange(\n total > 0 ? String(total) : \"\",\n \"send\",\n );\n }}\n style={{\n width: \"18px\",\n height: \"18px\",\n borderRadius: \"999px\",\n backgroundColor: \"var(--nexus-widget-surface-raised, #F0F0EF)\",\n border: \"none\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n flexShrink: 0,\n }}\n >\n \n \n \n \n \n )}\n \n \n\n {/* USD value + balance row */}\n \n \n {showSourceRouteSkeleton ? (\n \n ) : (\n (() => {\n if (!token)\n return (\n \n ≈ ${usdValue || \"0.00\"}\n \n );\n const tokenBalance =\n parseDecimal(token.balance)?.toNumber() ?? 0;\n const fiatBalance =\n parseDecimal(token.balanceInFiat)?.toNumber() ?? 0;\n const price =\n tokenBalance > 0 ? fiatBalance / tokenBalance : 0;\n const isUsdMode = token.userAmountMode === \"usd\";\n const userAmtNum = Number(token.userAmount || 0);\n const quotedUsd = parseDecimal(token.userAmountUsd);\n const approxValue = isUsdMode\n ? price > 0\n ? (userAmtNum / price).toFixed(6)\n : \"0.000000\"\n : quotedUsd\n ? quotedUsd.toDecimalPlaces(2).toFixed()\n : (userAmtNum * price).toFixed(2);\n const approxPrefix = isUsdMode ? \"≈\" : \"≈ $\";\n const approxSuffix = isUsdMode\n ? ` ${token.symbol}`\n : \"\";\n\n return (\n handleToggleMode(index)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n cursor:\n price > 0 && !isAmountReadOnly\n ? \"pointer\"\n : \"default\",\n }}\n >\n \n {approxPrefix}\n {approxValue}\n {approxSuffix}\n \n {price > 0 && }\n \n );\n })()\n )}\n \n\n \n {token && !isAmountReadOnly && (\n \n token\n ? handleSendPercentForToken(index, pct, token)\n : handleSendPercent(pct)\n }\n visible={Boolean(token) && focusedRow === index}\n />\n )}\n \n\n \n {showSourceRouteSkeleton || isBalanceLoading ? (\n \n ) : token ? (\n {\n setTooltip(`asset-send-${index}`);\n setTooltipTriggerRect(\n e.currentTarget.getBoundingClientRect(),\n );\n }}\n onMouseLeave={() => {\n setTooltip(null);\n setTooltipTriggerRect(null);\n }}\n style={{\n alignItems: \"center\",\n boxSizing: \"border-box\",\n display: \"flex\",\n gap: \"4px\",\n position: \"relative\",\n cursor: \"default\",\n whiteSpace: \"nowrap\",\n }}\n >\n \n Balance ·\n \n \n {formatTokenBalanceLabel(token)}\n \n\n {/* Tooltip */}\n {tooltip === `asset-send-${index}` &&\n tooltipTriggerRect &&\n createPortal(\n \n \n Asset Balance\n \n \n This is your current asset balance on this\n chain.\n \n ,\n document.body,\n )}\n \n ) : null}\n \n \n\n {/* PercentButtons moved inline next to balance */}\n \n );\n })}\n \n\n {hasSourceOverflow && (\n {\n const element = sourceListRef.current;\n if (!element) return;\n element.scrollTo({\n behavior: \"smooth\",\n top: isSourceListAtBottom ? 0 : element.scrollTop + 80,\n });\n }}\n style={{\n alignItems: \"center\",\n alignSelf: \"center\",\n background: \"transparent\",\n border: \"none\",\n color: \"var(--nexus-widget-text-secondary, #686866)\",\n cursor: \"pointer\",\n display: \"flex\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"13px\",\n fontWeight: 500,\n gap: \"4px\",\n lineHeight: \"18px\",\n marginTop: \"-2px\",\n padding: 0,\n }}\n type=\"button\"\n >\n Scroll to view more assets\n {isSourceListAtBottom ? \"↑\" : \"↓\"}\n \n )}\n\n {sourceRouteHelper && (\n \n {sourceRouteHelper}\n \n )}\n\n {/* Total USD */}\n {totalUsd > 0 && (\n \n \n ≈ ${totalUsd.toFixed(2)}\n \n \n TOTAL\n \n \n )}\n \n\n {/* ─── RECEIVE PANEL ─── */}\n \n \n Receive\n \n\n \n \n {isReceiveAmountLoading ? (\n \n \n \n ) : (\n \n )}\n\n {/* Destination asset pill */}\n \n {toToken ? (\n \n \n {toToken.chainLogo && (\n \n )}\n \n ) : (\n \n )}\n \n {toToken ? toToken.symbol : \"Assets\"}\n \n {!hideDestinationTokenDropdownIcon && }\n \n \n\n {/* USD value + balance row */}\n \n {isReceiveUsdLoading ? (\n \n ) : (\n \n {receiveAltValue}\n \n )}\n {toToken && focusedPanel === \"receive\" && (\n setTooltip(\"asset-receive\")}\n onMouseLeave={() => setTooltip(null)}\n style={{\n alignItems: \"center\",\n boxSizing: \"border-box\",\n display: \"flex\",\n gap: \"5px\",\n position: \"relative\",\n cursor: \"default\",\n }}\n >\n \n Asset Balance ·\n \n \n {isBalanceLoading ? (\n \n ) : (\n receiveBalanceLabel\n )}\n \n\n {/* Tooltip */}\n {tooltip === \"asset-receive\" && (\n \n \n Asset Balance\n \n \n This is your current asset balance on this chain.\n \n \n )}\n \n )}\n \n \n\n {/* Recipient section — only shown when handler exists */}\n {onOpenRecipientPicker && (\n <>\n \n \n \n Recipient\n \n \n \n {recipientAddress\n ? formatShortAddress(recipientAddress)\n : \"Select recipient\"}\n \n \n \n Edit\n \n \n \n \n \n )}\n \n \n );\n}\n", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\nimport Decimal from \"decimal.js\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport { useNexusWidgetThemeStyle } from \"../theme-context\";\nimport {\n formatSelectedTokenBalanceLabel,\n formatUsdBalanceLabel,\n type SwapTokenOption,\n} from \"./swap-asset-selector\";\n\nconst tabularNums: React.CSSProperties = {\n fontFeatureSettings: '\"tnum\"',\n fontVariantNumeric: \"tabular-nums\",\n};\n\nconst brand = \"var(--foreground-brand)\";\n\ninterface SwapIdleFormProps {\n amount: string;\n defaultRecipientAddress?: string;\n fromTokens: SwapTokenOption[];\n isAmountReadOnly?: boolean;\n isBalanceLoading?: boolean;\n isDestinationPickerDisabled?: boolean;\n hideDestinationTokenDropdownIcon?: boolean;\n isReceiveAmountLoading?: boolean;\n isReceiveUsdLoading?: boolean;\n isSourcePickerDisabled?: boolean;\n onAmountChange: (val: string, panel: \"send\" | \"receive\") => void;\n onOpenDestPicker: () => void;\n onOpenRecipientPicker?: () => void;\n onOpenSourcePicker: (index?: number) => void;\n onUpdateTokens?: (tokens: SwapTokenOption[]) => void;\n receiveQuoteAmount?: string;\n receiveQuoteUsd?: string;\n recipientAddress?: string;\n sourceRouteMessage?: string;\n sourceRouteStatus?: \"loading\" | \"insufficient\";\n swapType: \"exactIn\" | \"exactOut\";\n toToken?: SwapTokenOption;\n totalBalance: string;\n usdValue: string;\n}\n\n/** Chevron down icon used in asset selector pills */\nconst ChevronDownIcon = () => (\n \n \n \n);\n\nconst ArrowUpDownIcon = () => (\n \n \n \n);\n\n/** Reusable percentage quick-select buttons row with transition wrapper */\nfunction PercentButtons({\n visible,\n onSelect,\n maxLabel = \"Max\",\n token,\n}: {\n visible: boolean;\n onSelect: (pct: number) => void;\n maxLabel?: string;\n token: SwapTokenOption;\n}) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [hoveredPct, setHoveredPct] = useState(null);\n const isUsdMode = token.userAmountMode === \"usd\";\n const balance = parseDecimal(isUsdMode ? token.balanceInFiat : token.balance);\n const enteredAmount = parseDecimal(token.userAmount);\n const decimals = isUsdMode\n ? MAX_AMOUNT_DISPLAY_DECIMALS\n : getTokenInputDecimals(token);\n\n return (\n \n {[20, 50, 100].map((pct) => {\n const label = pct === 100 ? maxLabel : `${pct}%`;\n const isHovered = hoveredPct === pct;\n const isSelected = Boolean(\n balance?.gt(0) &&\n enteredAmount?.gt(0) &&\n enteredAmount.eq(\n balance\n .mul(pct)\n .div(100)\n .toDecimalPlaces(decimals, Decimal.ROUND_DOWN),\n ),\n );\n\n return (\n {\n e.stopPropagation();\n onSelect(pct);\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n }}\n onMouseEnter={() => setHoveredPct(pct)}\n onMouseLeave={() => setHoveredPct(null)}\n style={{\n alignItems: \"center\",\n backgroundColor: isHovered\n ? \"var(--nexus-widget-surface, #FFFFFF)\"\n : \"transparent\",\n borderRadius: \"4px\",\n boxShadow: isHovered\n ? \"var(--nexus-widget-shadow-soft, #3C286414) 0px 1px 2px\"\n : \"none\",\n boxSizing: \"border-box\",\n color: isHovered\n ? \"var(--nexus-widget-text, #1F1F1F)\"\n : \"var(--nexus-widget-text-secondary, #8E8E89)\",\n cursor: \"pointer\",\n display: \"flex\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"10px\",\n fontWeight: 500,\n height: \"18px\",\n justifyContent: \"center\",\n flex: \"1 1 0%\",\n minWidth: 0,\n paddingInline: \"3px\",\n border: \"none\",\n transition: \"all 0.15s ease-out\",\n }}\n tabIndex={-1}\n type=\"button\"\n >\n {label}\n \n );\n })}\n \n );\n}\n\nfunction UnifiedTokenLogoBadge({\n token,\n size = 24,\n}: {\n token: SwapTokenOption;\n size?: number;\n}) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [popover, setPopover] = useState<{\n left: number;\n top: number;\n width: number;\n maxHeight: number;\n } | null>(null);\n const triggerRef = useRef(null);\n const sources = token.sourceTokens ?? [];\n const chainCount =\n new Set(\n sources\n .map((source) => source.chainId ?? source.chainName)\n .filter(Boolean),\n ).size || sources.length;\n\n const showPopover = () => {\n const rect = triggerRef.current?.getBoundingClientRect();\n if (!rect || typeof window === \"undefined\") return;\n const width = 250;\n const maxHeight = 260;\n const viewportPadding = 8;\n const left = Math.min(\n Math.max(viewportPadding, rect.right - width),\n window.innerWidth - width - viewportPadding,\n );\n const belowTop = rect.bottom + 8;\n const top =\n belowTop + maxHeight > window.innerHeight\n ? Math.max(viewportPadding, rect.top - maxHeight - 8)\n : belowTop;\n setPopover({ left, top, width, maxHeight });\n };\n\n return (\n setPopover(null)}\n ref={triggerRef}\n style={{\n boxSizing: \"border-box\",\n flexShrink: 0,\n height: `${size}px`,\n position: \"relative\",\n width: `${size}px`,\n }}\n >\n \n {chainCount > 0 && (\n 9 ? \"3px\" : 0,\n position: \"absolute\",\n right: -3,\n }}\n >\n {chainCount}\n \n )}\n {popover &&\n sources.length > 0 &&\n typeof document !== \"undefined\" &&\n createPortal(\n \n \n \n Unified · {chainCount} {chainCount === 1 ? \"Chain\" : \"Chains\"}\n \n \n ≈ {formatUsdBalanceLabel(token.balanceInFiat)}\n \n \n \n {sources.map((source) => (\n \n \n \n \n {source.chainName || \"Unknown chain\"}\n \n \n \n {formatAmountInputDisplay(source.balance || \"0\")}\n \n \n ))}\n \n ,\n document.body,\n )}\n \n );\n}\n\nfunction PercentHoverButton({\n label,\n onClick,\n tabIndex,\n}: {\n label: string;\n onClick: () => void;\n tabIndex?: number;\n}) {\n const [hover, setHover] = useState(false);\n const [active, setActive] = useState(false);\n const handledPointerDownRef = useRef(false);\n const pointerResetTimerRef = useRef | null>(\n null,\n );\n\n useEffect(() => {\n return () => {\n if (pointerResetTimerRef.current) {\n clearTimeout(pointerResetTimerRef.current);\n }\n };\n }, []);\n\n const isHighlighted = hover || active;\n\n return (\n {\n if (handledPointerDownRef.current) {\n if (pointerResetTimerRef.current) {\n clearTimeout(pointerResetTimerRef.current);\n pointerResetTimerRef.current = null;\n }\n handledPointerDownRef.current = false;\n return;\n }\n onClick();\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n setActive(true);\n }}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => {\n setHover(false);\n setActive(false);\n }}\n onMouseUp={() => setActive(false)}\n onPointerDown={(event) => {\n if (event.pointerType === \"mouse\") return;\n event.preventDefault();\n if (pointerResetTimerRef.current) {\n clearTimeout(pointerResetTimerRef.current);\n }\n handledPointerDownRef.current = true;\n setActive(true);\n onClick();\n }}\n onPointerUp={() => {\n setActive(false);\n if (handledPointerDownRef.current) {\n pointerResetTimerRef.current = setTimeout(() => {\n handledPointerDownRef.current = false;\n pointerResetTimerRef.current = null;\n }, 350);\n }\n }}\n style={{\n alignItems: \"center\",\n backgroundColor: isHighlighted\n ? \"var(--nexus-widget-primary-soft, #E8F0FF)\"\n : \"var(--nexus-widget-surface-raised, #F4F4F3)\",\n borderRadius: \"6px\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flex: \"1 1 0%\",\n justifyContent: \"center\",\n paddingBlock: \"3px\",\n paddingInline: \"6px\",\n border: \"none\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s ease-out\",\n }}\n tabIndex={tabIndex}\n >\n \n {label}\n \n \n );\n}\n\nfunction SkeletonBar({\n width,\n height,\n borderRadius = \"8px\",\n}: {\n width: string;\n height: string;\n borderRadius?: string;\n}) {\n return (\n \n );\n}\n\nfunction LogoCircle({\n src,\n alt,\n label,\n size,\n fontSize,\n outline,\n style,\n}: {\n src?: string;\n alt?: string;\n label?: string;\n size: number;\n fontSize: number;\n outline?: string;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n const fallbackLabel = (label || alt || \"?\").trim().slice(0, 1).toUpperCase();\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderRadius: \"999px\",\n height: `${size}px`,\n objectFit: \"cover\",\n outline,\n width: `${size}px`,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {fallbackLabel || \"?\"}\n \n );\n}\n\nconst sameAddress = (a?: string, b?: string) =>\n Boolean(a && b && a.toLowerCase() === b.toLowerCase());\n\nconst formatShortAddress = (address?: string) => {\n if (!address) return \"\";\n return address.length > 12\n ? `${address.slice(0, 6)}…${address.slice(-4)}`\n : address;\n};\n\nconst formatTokenBalanceLabel = formatSelectedTokenBalanceLabel;\n\nconst formatUsdValue = (value: Decimal) =>\n value.gt(0) && value.lt(0.01) ? \"<0.01\" : value.toDecimalPlaces(2).toFixed(2);\n\nconst MAX_AMOUNT_DISPLAY_DECIMALS = 8;\nconst getTokenInputDecimals = (token?: Pick) => {\n const decimals = Number(token?.decimals);\n return Number.isFinite(decimals) && decimals >= 0 ? Math.floor(decimals) : 18;\n};\n\nconst formatAmountInputDisplay = (value: string) => {\n if (!value) return \"\";\n try {\n return new Decimal(value)\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n } catch {\n return value;\n }\n};\n\nexport function SwapIdleForm({\n amount,\n receiveQuoteAmount,\n receiveQuoteUsd,\n isReceiveAmountLoading = false,\n isReceiveUsdLoading = false,\n sourceRouteStatus,\n sourceRouteMessage,\n onAmountChange,\n fromTokens,\n toToken,\n totalBalance,\n usdValue,\n onOpenSourcePicker,\n onOpenDestPicker,\n onOpenRecipientPicker,\n recipientAddress,\n defaultRecipientAddress,\n swapType,\n onUpdateTokens,\n isAmountReadOnly = false,\n isBalanceLoading = false,\n isDestinationPickerDisabled = false,\n hideDestinationTokenDropdownIcon = false,\n isSourcePickerDisabled = false,\n}: SwapIdleFormProps) {\n const themeStyle = useNexusWidgetThemeStyle();\n const [focusedPanel, setFocusedPanel] = useState<\"send\" | \"receive\" | null>(\n null,\n );\n const [focusedRow, setFocusedRow] = useState(null);\n const [tooltip, setTooltip] = useState(null);\n const [tooltipTriggerRect, setTooltipTriggerRect] = useState(\n null,\n );\n const sourceListRef = useRef(null);\n const sourceRowRefs = useRef>({});\n const sourceInputRefs = useRef>({});\n const previousSourceCountRef = useRef(fromTokens.length);\n const prevTokensRef = useRef(fromTokens);\n const [autofocusIndex, setAutofocusIndex] = useState(null);\n\n useEffect(() => {\n const prev = prevTokensRef.current;\n if (fromTokens.length > prev.length) {\n setAutofocusIndex(fromTokens.length - 1);\n } else if (fromTokens.length === prev.length) {\n for (let i = 0; i < fromTokens.length; i++) {\n const p = prev[i];\n const c = fromTokens[i];\n if (\n p &&\n c &&\n (p.contractAddress !== c.contractAddress ||\n p.chainId !== c.chainId) &&\n !c.userAmount\n ) {\n setAutofocusIndex(i);\n break;\n }\n }\n }\n prevTokensRef.current = fromTokens;\n }, [fromTokens]);\n\n useEffect(() => {\n const previousSourceCount = previousSourceCountRef.current;\n if (fromTokens.length > previousSourceCount && previousSourceCount > 0) {\n const newIndex = fromTokens.length - 1;\n requestAnimationFrame(() => {\n const input = sourceInputRefs.current[newIndex];\n if (input) {\n input.focus();\n input.select();\n }\n\n const container = sourceListRef.current;\n const row = sourceRowRefs.current[newIndex];\n if (\n !container ||\n !row ||\n container.scrollHeight <= container.clientHeight\n ) {\n return;\n }\n\n const containerRect = container.getBoundingClientRect();\n const rowRect = row.getBoundingClientRect();\n const nextTop =\n rowRect.top - containerRect.top + container.scrollTop - 8;\n\n container.scrollTo({\n behavior: \"smooth\",\n top: Math.max(0, nextTop),\n });\n });\n }\n previousSourceCountRef.current = fromTokens.length;\n }, [fromTokens.length]);\n\n const sanitizeInput = (raw: string, maxDecimals = 18): string => {\n let next = raw.replaceAll(/[^0-9.]/g, \"\");\n const parts = next.split(\".\");\n if (parts.length > 2) next = parts[0] + \".\" + parts.slice(1).join(\"\");\n const [integerPart, decimalPart] = next.split(\".\");\n if (decimalPart !== undefined) {\n next = `${integerPart}.${decimalPart.slice(0, Math.max(0, maxDecimals))}`;\n }\n if (next === \".\") next = \"0.\";\n // Strip leading zeros\n if (next.length > 1 && next.startsWith(\"0\") && next[1] !== \".\") {\n next = next.replace(/^0+/, \"\");\n if (next === \"\") next = \"0\";\n if (next.startsWith(\".\")) next = \"0\" + next;\n }\n return next;\n };\n\n const handleBlurAmount = (index: number) => {\n if (!onUpdateTokens) return;\n const token = fromTokens[index];\n if (!token || !token.userAmount) return;\n if (token.userAmount.includes(\".\")) {\n const stripped = token.userAmount.replace(/0+$/, \"\").replace(/\\.$/, \"\");\n if (stripped !== token.userAmount) {\n const next = [...fromTokens];\n next[index] = { ...token, userAmount: stripped };\n onUpdateTokens(next);\n }\n }\n };\n\n const handleSendInput = (e: React.ChangeEvent) => {\n if (isAmountReadOnly) return;\n const token = fromTokens.length === 1 ? fromTokens[0] : undefined;\n onAmountChange(\n sanitizeInput(e.target.value, getTokenInputDecimals(token)),\n \"send\",\n );\n };\n\n const handleTokenAmountChange = (index: number, val: string) => {\n if (isAmountReadOnly) return;\n if (!onUpdateTokens) return;\n const token = fromTokens[index];\n if (!token) return;\n\n let sanitized = sanitizeInput(\n val,\n token.userAmountMode === \"usd\"\n ? MAX_AMOUNT_DISPLAY_DECIMALS\n : getTokenInputDecimals(token),\n );\n\n const next = [...fromTokens];\n next[index] = { ...token, userAmount: sanitized };\n onUpdateTokens(next);\n\n // Also update total amount for backwards compatibility if needed\n const total = next.reduce((sum, t) => sum + Number(t.userAmount || 0), 0);\n onAmountChange(total > 0 ? String(total) : \"\", \"send\");\n };\n\n const handleToggleMode = (index: number) => {\n if (isAmountReadOnly) return;\n if (!onUpdateTokens) return;\n const token = fromTokens[index];\n if (!token) return;\n\n const tokenBalance = parseDecimal(token.balance)?.toNumber() ?? 0;\n const fiatBalance = parseDecimal(token.balanceInFiat)?.toNumber() ?? 0;\n const price = tokenBalance > 0 ? fiatBalance / tokenBalance : 0;\n if (price === 0) return;\n\n const currentVal = Number(token.userAmount || 0);\n const next = [...fromTokens];\n if (token.userAmountMode === \"usd\") {\n const newTokenVal = currentVal > 0 ? (currentVal / price).toString() : \"\";\n next[index] = {\n ...token,\n userAmountMode: \"token\",\n userAmount: newTokenVal ? newTokenVal.substring(0, 10) : \"\",\n };\n } else {\n const newUsdVal = currentVal > 0 ? (currentVal * price).toFixed(2) : \"\";\n next[index] = { ...token, userAmountMode: \"usd\", userAmount: newUsdVal };\n }\n onUpdateTokens(next);\n const total = getTokenAmountTotal(next);\n onAmountChange(total > 0 ? String(total) : \"\", \"send\");\n };\n\n const getSourceUsdValue = React.useCallback((token: SwapTokenOption) => {\n if (!token || !token.userAmount) return 0;\n const quotedUsd = parseDecimal(token.userAmountUsd);\n if (quotedUsd && quotedUsd.gte(0)) return quotedUsd.toNumber();\n const tokenBalance = parseDecimal(token.balance)?.toNumber() ?? 0;\n const fiatBalance = parseDecimal(token.balanceInFiat)?.toNumber() ?? 0;\n const price = tokenBalance > 0 ? fiatBalance / tokenBalance : 0;\n const amountNumber = Number(token.userAmount || 0);\n if (!Number.isFinite(amountNumber)) return 0;\n if (token.userAmountMode === \"usd\") return amountNumber;\n return amountNumber * price;\n }, []);\n\n const totalUsd = React.useMemo(() => {\n return fromTokens.reduce((sum, token) => sum + getSourceUsdValue(token), 0);\n }, [fromTokens, getSourceUsdValue]);\n\n const hasSourceOverflow = fromTokens.length > 3;\n const [isSourceListAtBottom, setIsSourceListAtBottom] = useState(false);\n const updateSourceListScrollState = React.useCallback(() => {\n const element = sourceListRef.current;\n if (!element || !hasSourceOverflow) {\n setIsSourceListAtBottom(false);\n return;\n }\n\n const distanceFromBottom =\n element.scrollHeight - element.scrollTop - element.clientHeight;\n setIsSourceListAtBottom(distanceFromBottom <= 2);\n }, [hasSourceOverflow]);\n\n useEffect(() => {\n requestAnimationFrame(updateSourceListScrollState);\n }, [fromTokens.length, updateSourceListScrollState]);\n\n const sourceRowsToRender: Array<{\n token: SwapTokenOption | null;\n index: number;\n position: number;\n }> =\n fromTokens.length > 0\n ? fromTokens.map((token, index) => ({ token, index, position: index }))\n : [{ token: null, index: 0, position: 0 }];\n\n const isExactIn = swapType === \"exactIn\";\n const showSourceRouteSkeleton = !isExactIn && sourceRouteStatus === \"loading\";\n const sourceRouteHelper =\n sourceRouteStatus === \"insufficient\" ? sourceRouteMessage : undefined;\n const receiveBalanceLabel = formatTokenBalanceLabel(toToken);\n const getReceiveUsdRate = () => {\n const quoteTokenAmount = parseDecimal(receiveQuoteAmount);\n const quoteUsdAmount = parseDecimal(receiveQuoteUsd);\n if (quoteTokenAmount?.gt(0) && quoteUsdAmount?.gt(0)) {\n return quoteUsdAmount.div(quoteTokenAmount);\n }\n\n const tokenBalance = parseDecimal(toToken?.balance);\n const fiatBalance = parseDecimal(toToken?.balanceInFiat);\n if (tokenBalance?.gt(0) && fiatBalance?.gt(0)) {\n return fiatBalance.div(tokenBalance);\n }\n\n return undefined;\n };\n const receiveInputValue = isExactIn ? (receiveQuoteAmount ?? \"\") : amount;\n const receiveDisplayValue =\n focusedPanel === \"receive\"\n ? receiveInputValue\n : formatAmountInputDisplay(receiveInputValue);\n const receiveAmountTextColor =\n (!isExactIn && amount) || (isExactIn && receiveQuoteAmount)\n ? \"var(--nexus-widget-text-strong, #161615)\"\n : \"var(--nexus-widget-text-tertiary, #9E9E9C)\";\n const receiveUsdRate = getReceiveUsdRate();\n const receiveTokenAmount = parseDecimal(receiveInputValue);\n const receiveUsdAmount = receiveQuoteUsd\n ? parseDecimal(receiveQuoteUsd)\n : receiveTokenAmount && receiveUsdRate\n ? receiveTokenAmount.mul(receiveUsdRate)\n : undefined;\n const receiveAltValue = `≈ $${\n receiveUsdAmount ? formatUsdValue(receiveUsdAmount) : \"0.00\"\n }`;\n const isDefaultRecipient = sameAddress(\n recipientAddress,\n defaultRecipientAddress,\n );\n const recipientColor = recipientAddress\n ? isDefaultRecipient\n ? \"var(--nexus-widget-primary-soft-text, var(--foreground-brand))\"\n : \"var(--nexus-widget-warning-text, #B7791F)\"\n : \"var(--nexus-widget-text-secondary, #848483)\";\n const getTokenAmountTotal = (tokens: SwapTokenOption[]) =>\n tokens.reduce((sum, item) => sum + Number(item.userAmount || 0), 0);\n\n const handleSendPercentForToken = (\n index: number,\n pct: number,\n token: SwapTokenOption,\n ) => {\n if (isAmountReadOnly) return;\n if (!token.balance || !onUpdateTokens) return;\n let finalVal = \"\";\n const isUsdMode = token.userAmountMode === \"usd\";\n\n if (isUsdMode) {\n const fiatBalStr = String(token.balanceInFiat || \"0\");\n const fiatBalance = parseDecimal(fiatBalStr);\n if (!fiatBalance) return;\n if (pct === 100) {\n finalVal = fiatBalance\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n } else {\n finalVal = fiatBalance\n .mul(pct)\n .div(100)\n .toDecimalPlaces(MAX_AMOUNT_DISPLAY_DECIMALS, Decimal.ROUND_DOWN)\n .toFixed();\n }\n } else {\n const balanceStr = String(token.balance || \"0\");\n const tokenBalance = parseDecimal(balanceStr);\n if (!tokenBalance) return;\n const tokenDecimals = getTokenInputDecimals(token);\n if (pct === 100) {\n finalVal = tokenBalance\n .toDecimalPlaces(tokenDecimals, Decimal.ROUND_DOWN)\n .toFixed();\n } else {\n finalVal = tokenBalance\n .mul(pct)\n .div(100)\n .toDecimalPlaces(tokenDecimals, Decimal.ROUND_DOWN)\n .toFixed();\n }\n }\n\n const next = [...fromTokens];\n next[index] = {\n ...next[index],\n userAmount: finalVal,\n userAmountMode: isUsdMode ? \"usd\" : \"token\",\n };\n onUpdateTokens(next);\n const total = getTokenAmountTotal(next);\n onAmountChange(total > 0 ? String(total) : \"\", \"send\");\n };\n\n const handleSendPercent = (pct: number) => {\n if (isAmountReadOnly) return;\n if (!totalBalance) return;\n const bal = parseFloat(totalBalance.replace(/[^0-9.]/g, \"\"));\n if (isNaN(bal)) return;\n const val = bal * (pct / 100);\n // If there's only one token, or no tokens, update the main amount\n if (fromTokens.length <= 1) {\n if (fromTokens.length === 1 && onUpdateTokens) {\n handleSendPercentForToken(0, pct, fromTokens[0]);\n return;\n }\n onAmountChange(val.toFixed(6).replace(/\\.?0+$/, \"\"), \"send\");\n }\n };\n\n return (\n \n {(isReceiveAmountLoading || isReceiveUsdLoading || sourceRouteStatus) && (\n \n )}\n {/* ─── SEND PANEL ─── */}\n \n {/* Header row: SEND + add asset */}\n \n \n Send\n \n onOpenSourcePicker()}\n style={{\n alignItems: \"center\",\n background: \"transparent\",\n border: \"none\",\n borderRadius: \"6px\",\n display: \"flex\",\n gap: \"4px\",\n padding: \"2px 0\",\n color:\n fromTokens.length > 0 && !isSourcePickerDisabled\n ? \"var(--nexus-widget-primary-soft-text, var(--foreground-brand))\"\n : \"var(--nexus-widget-text-secondary, #A8A8A6)\",\n cursor:\n fromTokens.length > 0 && !isSourcePickerDisabled\n ? \"pointer\"\n : \"not-allowed\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"12px\",\n fontWeight: 500,\n lineHeight: \"18px\",\n opacity:\n fromTokens.length > 0 && !isSourcePickerDisabled ? 1 : 0.75,\n }}\n type=\"button\"\n >\n \n +\n \n Add more assets\n \n \n\n {/* Render each selected source asset, or an empty one if none */}\n \n {sourceRowsToRender.map(({ token, index, position }) => {\n const showTooltipBelow = position === 0;\n return (\n {\n sourceRowRefs.current[index] = element;\n }}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"5px\",\n opacity: 1,\n position: \"relative\",\n transform: \"translateY(0)\",\n transition: \"opacity 0.18s ease, transform 0.18s ease\",\n zIndex: tooltip === `asset-send-${index}` ? 1000 : 1,\n }}\n >\n \n \n {showSourceRouteSkeleton ? (\n \n ) : (\n <>\n {token?.userAmountMode === \"usd\" && (\n \n $\n \n )}\n {\n if (token) handleBlurAmount(index);\n setFocusedRow(null);\n }}\n onChange={(e) => {\n if (token)\n handleTokenAmountChange(index, e.target.value);\n else handleSendInput(e);\n }}\n onFocus={() => setFocusedRow(index)}\n placeholder=\"0\"\n ref={(element) => {\n sourceInputRefs.current[index] = element;\n }}\n style={{\n boxSizing: \"border-box\",\n color: (\n token\n ? Boolean(token.userAmount)\n : Boolean(isExactIn && amount)\n )\n ? \"var(--nexus-widget-text-strong, #161615)\"\n : \"var(--nexus-widget-text-tertiary, #9E9E9C)\",\n cursor: isAmountReadOnly ? \"default\" : \"text\",\n fontFamily:\n '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"29px\",\n fontWeight: 500,\n lineHeight: \"34px\",\n background: \"transparent\",\n border: \"none\",\n outline: \"none\",\n padding: 0,\n width: \"100%\",\n minWidth: 0,\n }}\n readOnly={isAmountReadOnly}\n type=\"text\"\n value={\n token\n ? focusedRow === index\n ? token.userAmount || \"\"\n : formatAmountInputDisplay(\n token.userAmount || \"\",\n )\n : isExactIn\n ? focusedRow === index\n ? amount\n : formatAmountInputDisplay(amount)\n : \"\"\n }\n />\n \n )}\n \n\n {/* Asset selector pill + cross button */}\n \n {showSourceRouteSkeleton ? (\n \n \n \n ) : (\n onOpenSourcePicker(index)}\n style={{\n alignItems: \"center\",\n backgroundColor:\n \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderColor: token\n ? \"var(--nexus-widget-border, #E8E8E7)\"\n : \"var(--nexus-widget-border-empty, #C8C8C7)\",\n borderRadius: \"999px\",\n borderStyle: token ? \"solid\" : \"dashed\",\n borderWidth: \"1px\",\n boxShadow: token\n ? \"var(--nexus-widget-shadow-soft, #1616150A) 0px 1px 2px\"\n : \"none\",\n boxSizing: \"border-box\",\n display: \"flex\",\n gap: \"8px\",\n paddingBottom: \"5px\",\n paddingLeft: token ? \"5px\" : \"10px\",\n paddingRight: \"10px\",\n paddingTop: \"5px\",\n cursor: isSourcePickerDisabled\n ? \"not-allowed\"\n : \"pointer\",\n flexShrink: 0,\n opacity: isSourcePickerDisabled ? 0.72 : 1,\n }}\n >\n {token ? (\n token.isUnified ? (\n \n ) : (\n \n \n {token.chainLogo && (\n \n )}\n \n )\n ) : (\n \n )}\n \n {token ? token.symbol : \"Assets\"}\n \n \n \n )}\n {token && fromTokens.length > 1 && (\n {\n if (!onUpdateTokens) return;\n const next = [...fromTokens];\n next.splice(index, 1);\n onUpdateTokens(next);\n const total = getTokenAmountTotal(next);\n onAmountChange(\n total > 0 ? String(total) : \"\",\n \"send\",\n );\n }}\n style={{\n width: \"18px\",\n height: \"18px\",\n borderRadius: \"999px\",\n backgroundColor:\n \"var(--nexus-widget-surface-raised, #F0F0EF)\",\n border: \"none\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n flexShrink: 0,\n }}\n >\n \n \n \n \n \n )}\n \n \n\n {/* USD value + balance row */}\n \n \n {showSourceRouteSkeleton ? (\n \n ) : (\n (() => {\n if (!token)\n return (\n \n ≈ ${usdValue || \"0.00\"}\n \n );\n const tokenBalance =\n parseDecimal(token.balance)?.toNumber() ?? 0;\n const fiatBalance =\n parseDecimal(token.balanceInFiat)?.toNumber() ?? 0;\n const price =\n tokenBalance > 0 ? fiatBalance / tokenBalance : 0;\n const isUsdMode = token.userAmountMode === \"usd\";\n const userAmtNum = Number(token.userAmount || 0);\n const quotedUsd = parseDecimal(token.userAmountUsd);\n const approxValue = isUsdMode\n ? price > 0\n ? (userAmtNum / price).toFixed(6)\n : \"0.000000\"\n : quotedUsd\n ? quotedUsd.toDecimalPlaces(2).toFixed()\n : (userAmtNum * price).toFixed(2);\n const approxPrefix = isUsdMode ? \"≈\" : \"≈ $\";\n const approxSuffix = isUsdMode\n ? ` ${token.symbol}`\n : \"\";\n\n return (\n handleToggleMode(index)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n cursor:\n price > 0 && !isAmountReadOnly\n ? \"pointer\"\n : \"default\",\n }}\n >\n \n {approxPrefix}\n {approxValue}\n {approxSuffix}\n \n {price > 0 && }\n \n );\n })()\n )}\n \n\n \n {token && !isAmountReadOnly && (\n \n token\n ? handleSendPercentForToken(index, pct, token)\n : handleSendPercent(pct)\n }\n visible={Boolean(token) && focusedRow === index}\n />\n )}\n \n\n \n {showSourceRouteSkeleton || isBalanceLoading ? (\n \n ) : token ? (\n {\n setTooltip(`asset-send-${index}`);\n setTooltipTriggerRect(\n e.currentTarget.getBoundingClientRect(),\n );\n }}\n onMouseLeave={() => {\n setTooltip(null);\n setTooltipTriggerRect(null);\n }}\n style={{\n alignItems: \"center\",\n boxSizing: \"border-box\",\n display: \"flex\",\n gap: \"4px\",\n position: \"relative\",\n cursor: \"default\",\n whiteSpace: \"nowrap\",\n }}\n >\n \n Balance ·\n \n \n {formatTokenBalanceLabel(token)}\n \n\n {/* Tooltip */}\n {tooltip === `asset-send-${index}` &&\n tooltipTriggerRect &&\n createPortal(\n \n \n Asset Balance\n \n \n This is your current asset balance on this\n chain.\n \n ,\n document.body,\n )}\n \n ) : null}\n \n \n\n {/* PercentButtons moved inline next to balance */}\n \n );\n })}\n \n\n {hasSourceOverflow && (\n {\n const element = sourceListRef.current;\n if (!element) return;\n element.scrollTo({\n behavior: \"smooth\",\n top: isSourceListAtBottom ? 0 : element.scrollTop + 80,\n });\n }}\n style={{\n alignItems: \"center\",\n alignSelf: \"center\",\n background: \"transparent\",\n border: \"none\",\n color: \"var(--nexus-widget-text-secondary, #686866)\",\n cursor: \"pointer\",\n display: \"flex\",\n fontFamily: '\"Geist\", system-ui, sans-serif',\n fontSize: \"13px\",\n fontWeight: 500,\n gap: \"4px\",\n lineHeight: \"18px\",\n marginTop: \"-2px\",\n padding: 0,\n }}\n type=\"button\"\n >\n Scroll to view more assets\n {isSourceListAtBottom ? \"↑\" : \"↓\"}\n \n )}\n\n {sourceRouteHelper && (\n \n {sourceRouteHelper}\n \n )}\n\n {/* Total USD */}\n {totalUsd > 0 && (\n \n \n ≈ ${totalUsd.toFixed(2)}\n \n \n TOTAL\n \n \n )}\n \n\n {/* ─── RECEIVE PANEL ─── */}\n \n \n Receive\n \n\n \n \n {isReceiveAmountLoading ? (\n \n \n \n ) : (\n \n )}\n\n {/* Destination asset pill */}\n \n {toToken ? (\n \n \n {toToken.chainLogo && (\n \n )}\n \n ) : (\n \n )}\n \n {toToken ? toToken.symbol : \"Assets\"}\n \n {!hideDestinationTokenDropdownIcon && }\n \n \n\n {/* USD value + balance row */}\n \n {isReceiveUsdLoading ? (\n \n ) : (\n \n {receiveAltValue}\n \n )}\n {toToken && focusedPanel === \"receive\" && (\n setTooltip(\"asset-receive\")}\n onMouseLeave={() => setTooltip(null)}\n style={{\n alignItems: \"center\",\n boxSizing: \"border-box\",\n display: \"flex\",\n gap: \"5px\",\n position: \"relative\",\n cursor: \"default\",\n }}\n >\n \n Asset Balance ·\n \n \n {isBalanceLoading ? (\n \n ) : (\n receiveBalanceLabel\n )}\n \n\n {/* Tooltip */}\n {tooltip === \"asset-receive\" && (\n \n \n Asset Balance\n \n \n This is your current asset balance on this chain.\n \n \n )}\n \n )}\n \n \n\n {/* Recipient section — only shown when handler exists */}\n {onOpenRecipientPicker && (\n <>\n \n \n \n Recipient\n \n \n \n {recipientAddress\n ? formatShortAddress(recipientAddress)\n : \"Select recipient\"}\n \n \n \n Edit\n \n \n \n \n \n )}\n \n \n );\n}\n", "type": "registry:component", "target": "components/nexus/components/swap-idle-form.tsx" }, { "path": "registry/avail-widgets/nexus-widget/components/swap-intent-preview.tsx", - "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\n\"use client\";\n\nimport Decimal from \"decimal.js\";\nimport { ChevronDown, Info, Loader2 } from \"lucide-react\";\nimport React, { useRef, useState } from \"react\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport type { SwapStepType } from \"../../common/types/transaction-flow\";\nimport { CHAIN_METADATA, getShortChainName } from \"../../common/utils/constant\";\nimport TransactionProgress from \"../../swaps/components/transaction-progress\";\nimport { Button } from \"../../ui/button\";\nimport {\n type NexusWidgetDepositOpportunityMetadata,\n type NexusWidgetMode,\n} from \"../types\";\nimport { type SwapTokenOption } from \"./swap-asset-selector\";\n\nexport interface SwapIntentSource {\n amount: string;\n chain: { id: number; logo: string; name: string };\n token: {\n contractAddress: string;\n decimals: number;\n logo?: string;\n symbol: string;\n };\n value?: string;\n}\n\nexport interface SwapIntentDestination {\n amount: string;\n chain: { id: number; logo: string; name: string };\n gas: {\n amount: string;\n value?: string;\n token: {\n contractAddress: string;\n decimals: number;\n logo?: string;\n symbol: string;\n };\n };\n token: {\n contractAddress: string;\n decimals: number;\n logo?: string;\n symbol: string;\n };\n value?: string;\n}\n\nexport type BridgeProvider = \"nexus\" | \"mayan\" | null;\n\nexport interface SwapIntentData {\n bridgeProvider?: BridgeProvider;\n destination: SwapIntentDestination;\n feesAndBuffer?: {\n buffer?: string;\n bridge?:\n | {\n caGas?: string;\n collection?: string;\n fulfilment?: string;\n gasSupplied?: string;\n protocol?: string;\n solver?: string;\n total?: string;\n }\n | string\n | null;\n };\n sources: SwapIntentSource[];\n}\n\nexport interface SwapIntentPreviewProps {\n activeMode?: NexusWidgetMode;\n estimatedTime?: string;\n explorerUrls?: {\n sourceExplorerUrl: string | null;\n destinationExplorerUrl: string | null;\n };\n fromAmount: string;\n fromAmountUsd?: string;\n destinationGasFeeUsd?: string;\n fromToken?: SwapTokenOption;\n fromTokens?: SwapTokenOption[];\n intentData?: SwapIntentData | null;\n isExecuting?: boolean;\n isLoading?: boolean;\n isRefreshing?: boolean;\n mode?: NexusWidgetMode;\n onAccept: () => void;\n onReject: () => void;\n onTransitionChange?: (isTransitioning: boolean) => void;\n opportunity?: NexusWidgetDepositOpportunityMetadata;\n recipientAddress?: string;\n steps?: Array<{ id: number; completed: boolean; step: SwapStepType }>;\n supportedTokenAssets?: any[] | null;\n swapBalances?: any[] | null;\n swapType?: \"exactIn\" | \"exactOut\";\n toAmount?: string;\n toAmountTokens?: string;\n toAmountUsd?: string;\n toToken?: SwapTokenOption;\n totalFeeUsd?: string;\n}\n\nconst fontFamily = '\"Geist\", var(--font-geist-sans), system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\n\nconst toDecimal = (value: unknown) => parseDecimal(value) ?? new Decimal(0);\n\nconst formatAmount = (\n value: unknown,\n options: { min?: number; max?: number } = {},\n) => {\n const amount = toDecimal(value);\n const max = options.max ?? 2;\n return amount.toDecimalPlaces(max).toFixed();\n};\n\nconst formatUsdDelta = (value: Decimal) => {\n if (value.gt(0) && value.lt(0.01)) return \"-<0.01 USD\";\n return value.gt(0) ? `-${formatAmount(value)} USD` : \"0 USD\";\n};\n\nconst formatUsdAmount = (value: Decimal) => {\n if (value.gt(0) && value.lt(0.01)) return \"<0.01 USD\";\n return value.gt(0) ? `${formatAmount(value)} USD` : \"0 USD\";\n};\n\nconst formatUsdValue = (value: Decimal) => {\n const absolute = value.abs();\n if (absolute.eq(0)) return \"$0\";\n if (absolute.lt(0.01)) return value.lt(0) ? \"-<$0.01\" : \"<$0.01\";\n\n const amount = formatAmount(absolute, { max: 2 });\n\n return value.lt(0) ? `-$${amount}` : `$${amount}`;\n};\n\nconst formatTokenAmount = (value: unknown) => {\n const amount = toDecimal(value);\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst formatHeaderTokenAmount = (value: unknown) => {\n const amount = toDecimal(value);\n if (amount.isZero()) return \"0\";\n if (amount.abs().gte(1000)) {\n return amount.toDecimalPlaces(2).toFixed();\n }\n if (amount.abs().gte(1)) {\n return amount.toDecimalPlaces(4).toFixed();\n }\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst getFontSize = (amountStr: string, symbolStr: string) => {\n const totalLength =\n String(amountStr || \"\").length + String(symbolStr || \"\").length;\n if (totalLength > 16) return \"13px\";\n if (totalLength > 12) return \"15px\";\n return \"17px\";\n};\n\nconst unique = (values: string[]) =>\n Array.from(new Set(values.filter(Boolean)));\n\nconst isNativeTokenAddress = (address?: string) => {\n const lower = (address ?? \"\").toLowerCase();\n return (\n !lower ||\n lower === \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\" ||\n lower === \"0x0000000000000000000000000000000000000000\"\n );\n};\n\nconst getSourceDisplayKey = (\n chainId?: number | string,\n address?: string,\n symbol?: string,\n) => {\n const chainKey = chainId ?? \"\";\n const normalizedAddress = address?.toLowerCase();\n return normalizedAddress\n ? `${chainKey}-${normalizedAddress}`\n : `${chainKey}-symbol-${(symbol ?? \"\").toUpperCase()}`;\n};\n\nconst normalizeIntentToken = <\n T extends {\n contractAddress?: string;\n decimals?: number;\n logo?: string;\n symbol?: string;\n },\n>(\n token: T | undefined,\n chainId?: number,\n) => {\n const chainMeta = chainId ? CHAIN_METADATA[chainId] : undefined;\n const shouldUseNative =\n isNativeTokenAddress(token?.contractAddress) && Boolean(chainMeta);\n const symbol =\n shouldUseNative && chainMeta?.nativeCurrency.symbol\n ? chainMeta.nativeCurrency.symbol\n : token?.symbol || chainMeta?.nativeCurrency.symbol || \"-\";\n const decimals =\n shouldUseNative && chainMeta?.nativeCurrency.decimals !== undefined\n ? chainMeta.nativeCurrency.decimals\n : (token?.decimals ?? chainMeta?.nativeCurrency.decimals ?? 18);\n\n return {\n contractAddress: token?.contractAddress ?? \"\",\n decimals,\n logo: token?.logo || (shouldUseNative ? chainMeta?.logo : undefined),\n symbol,\n };\n};\n\nconst formatSymbolSummary = (symbols: string[]) => {\n const visible = unique(symbols);\n if (visible.length === 0) return \"-\";\n if (visible.length <= 2) return visible.join(\", \");\n if (visible.length === 3)\n return `${visible[0]}, ${visible[1]} and ${visible[2]}`;\n\n const others = visible.length - 2;\n return `${visible[0]}, ${visible[1]} and ${others} other${others === 1 ? \"\" : \"s\"}`;\n};\n\nconst sortSourceDetailRowsByUsdDesc = <\n T extends { symbol?: string; usdAmount?: string },\n>(\n rows: T[],\n) =>\n [...rows].sort((a, b) => {\n const usdDelta = toDecimal(b.usdAmount).cmp(toDecimal(a.usdAmount));\n if (usdDelta !== 0) return usdDelta;\n return (a.symbol ?? \"\").localeCompare(b.symbol ?? \"\");\n });\n\nfunction IntentLogo({\n src,\n alt,\n label,\n size,\n fontSize,\n outline,\n style,\n}: {\n src?: string;\n alt?: string;\n label?: string;\n size: number;\n fontSize: number;\n outline?: string;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n React.useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n const fallbackLabel = (label || alt || \"?\").trim().slice(0, 1).toUpperCase();\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n height: `${size}px`,\n objectFit: \"cover\",\n outline,\n width: `${size}px`,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {fallbackLabel || \"?\"}\n \n );\n}\n\nfunction DetailToggle({\n expanded,\n onClick,\n}: {\n expanded: boolean;\n onClick: () => void;\n}) {\n return (\n \n {expanded ? \"Hide Details\" : \"View Details\"}\n \n \n );\n}\n\nfunction TruncatedAddress({ address }: { address: string }) {\n const [showTooltip, setShowTooltip] = useState(false);\n const label =\n address.length > 12\n ? `${address.slice(0, 6)}...${address.slice(-4)}`\n : address;\n\n return (\n setShowTooltip(false)}\n onFocus={() => setShowTooltip(true)}\n onMouseEnter={() => setShowTooltip(true)}\n onMouseLeave={() => setShowTooltip(false)}\n style={{\n color: brand,\n display: \"inline-flex\",\n fontFamily,\n fontSize: \"13px\",\n fontWeight: 500,\n lineHeight: \"15px\",\n outline: \"none\",\n position: \"relative\",\n }}\n tabIndex={0}\n >\n {label}\n {showTooltip && (\n \n {address}\n \n )}\n \n );\n}\n\nfunction RecipientRow({ address }: { address: string }) {\n return (\n \n
\n \n Recipient\n
\n \n Wallet address\n \n \n
\n \n
\n \n );\n}\n\nfunction InlineInfoTooltip({ message }: { message: string }) {\n const [showTooltip, setShowTooltip] = useState(false);\n\n return (\n setShowTooltip(false)}\n onFocus={() => setShowTooltip(true)}\n onMouseEnter={() => setShowTooltip(true)}\n onMouseLeave={() => setShowTooltip(false)}\n style={{\n alignItems: \"center\",\n color: muted,\n display: \"inline-flex\",\n lineHeight: 0,\n outline: \"none\",\n position: \"relative\",\n }}\n tabIndex={0}\n >\n \n {showTooltip && (\n \n {message}\n \n )}\n \n );\n}\n\nfunction MayanPoweredBadge() {\n return (\n \n \n This transaction is powered by\n \n \n );\n}\n\nfunction Row({\n title,\n subtitle,\n value,\n secondaryValue,\n children,\n}: {\n title: React.ReactNode;\n subtitle: string;\n value: string;\n secondaryValue?: string;\n children?: React.ReactNode;\n}) {\n return (\n \n
\n \n {title}\n
\n \n {subtitle}\n \n \n \n \n {value}\n \n {secondaryValue ? (\n \n {secondaryValue}\n \n ) : (\n children\n )}\n \n \n );\n}\n\nfunction AnimatedDetails({\n open,\n children,\n background = \"var(--nexus-widget-background, #F9F9F8)\",\n gap = \"9px\",\n padding = \"12px 14px\",\n}: {\n open: boolean;\n children: React.ReactNode;\n background?: string;\n gap?: string;\n padding?: string;\n}) {\n return (\n \n
\n \n {children}\n
\n \n \n );\n}\n\nexport function SwapIntentPreview({\n fromTokens,\n fromToken,\n toToken,\n fromAmount,\n fromAmountUsd,\n destinationGasFeeUsd,\n toAmount,\n toAmountUsd,\n toAmountTokens,\n totalFeeUsd,\n isLoading,\n isRefreshing,\n isExecuting,\n swapType,\n intentData,\n mode,\n opportunity,\n recipientAddress,\n activeMode,\n steps,\n explorerUrls,\n onAccept,\n onTransitionChange,\n}: SwapIntentPreviewProps) {\n const [showSourceDetails, setShowSourceDetails] = useState(false);\n const [showFeeDetails, setShowFeeDetails] = useState(false);\n const [showImpactDetails, setShowImpactDetails] = useState(false);\n const sourceDetailsScrollRef = useRef(null);\n const [transitionTimeoutId, setTransitionTimeoutId] = useState | null>(null);\n\n const startTransition = () => {\n if (onTransitionChange) {\n onTransitionChange(true);\n }\n if (transitionTimeoutId) {\n clearTimeout(transitionTimeoutId);\n }\n const id = setTimeout(() => {\n if (onTransitionChange) {\n onTransitionChange(false);\n }\n setTransitionTimeoutId(null);\n }, 280);\n setTransitionTimeoutId(id);\n };\n\n React.useEffect(() => {\n return () => {\n if (transitionTimeoutId) {\n clearTimeout(transitionTimeoutId);\n }\n };\n }, [transitionTimeoutId]);\n\n const flowMode = mode ?? activeMode ?? \"swap\";\n const isDepositMode = flowMode === \"deposit\";\n const isSendMode = flowMode === \"send\";\n const hasRecipientTransfer = Boolean(recipientAddress) && !isDepositMode;\n const isExactOutDisplayFlow =\n (isDepositMode || isSendMode) && swapType === \"exactOut\";\n const shouldShowSwapBuffer = swapType !== \"exactIn\";\n const intentSources = intentData?.sources ?? [];\n const intentDest = intentData?.destination;\n const normalizedIntentSources = intentSources.map((source) => ({\n ...source,\n token: normalizeIntentToken(source.token, source.chain.id),\n }));\n const normalizedIntentDest = intentDest\n ? {\n ...intentDest,\n token: normalizeIntentToken(intentDest.token, intentDest.chain.id),\n gas: {\n ...intentDest.gas,\n token: normalizeIntentToken(\n intentDest.gas?.token,\n intentDest.chain.id,\n ),\n },\n }\n : undefined;\n const fallbackSources =\n fromTokens && fromTokens.length > 0\n ? fromTokens\n : fromToken\n ? [fromToken]\n : [];\n\n const baseSourceSymbols =\n normalizedIntentSources.length > 0\n ? unique(normalizedIntentSources.map((source) => source.token.symbol))\n : unique(fallbackSources.map((source) => source.symbol));\n const baseSourceAssetCount =\n normalizedIntentSources.length ||\n fallbackSources.length ||\n baseSourceSymbols.length;\n const hasResolvedQuote = Boolean(\n normalizedIntentDest &&\n (normalizedIntentSources.length > 0 || isExactOutDisplayFlow),\n );\n const quoteUnavailable = !isLoading && !hasResolvedQuote;\n\n const destTokenSymbol =\n normalizedIntentDest?.token.symbol ||\n toToken?.symbol ||\n opportunity?.tokenSymbol ||\n \"-\";\n const destChainName =\n flowMode === \"deposit\"\n ? opportunity?.title || opportunity?.protocol || \"App\"\n : getShortChainName(\n normalizedIntentDest?.chain.id ?? toToken?.chainId,\n normalizedIntentDest?.chain.name || toToken?.chainName || \"\",\n );\n\n const requestedDestinationAmount = isExactOutDisplayFlow\n ? parseDecimal(toAmountTokens ?? toAmount)\n : undefined;\n const quotedDestinationAmount = parseDecimal(normalizedIntentDest?.amount);\n const destinationBalanceAmount = parseDecimal(toToken?.balance);\n const displayOnlyDestinationCoverage = (() => {\n if (\n !isExactOutDisplayFlow ||\n !requestedDestinationAmount ||\n requestedDestinationAmount.lte(0) ||\n !destinationBalanceAmount ||\n destinationBalanceAmount.lte(0)\n ) {\n return undefined;\n }\n\n const externallyProducedAmount =\n normalizedIntentSources.length > 0 &&\n quotedDestinationAmount &&\n quotedDestinationAmount.gt(0)\n ? quotedDestinationAmount\n : new Decimal(0);\n const destinationBalanceAmountNeeded = Decimal.max(\n requestedDestinationAmount.minus(externallyProducedAmount),\n 0,\n );\n const coveredAmount = Decimal.min(\n destinationBalanceAmountNeeded,\n destinationBalanceAmount,\n );\n return coveredAmount.gt(0) ? coveredAmount : undefined;\n })();\n const displayOnlyDestinationSourceAmount = displayOnlyDestinationCoverage;\n const requestedDestinationUsd = parseDecimal(toAmountUsd);\n const destinationDisplayUsdRate =\n requestedDestinationAmount &&\n requestedDestinationAmount.gt(0) &&\n requestedDestinationUsd &&\n requestedDestinationUsd.gt(0)\n ? requestedDestinationUsd.div(requestedDestinationAmount)\n : quotedDestinationAmount &&\n quotedDestinationAmount.gt(0) &&\n normalizedIntentDest?.value\n ? (parseDecimal(normalizedIntentDest.value) ?? new Decimal(0)).div(\n quotedDestinationAmount,\n )\n : undefined;\n const displayOnlyDestinationCoverageUsd =\n displayOnlyDestinationCoverage &&\n displayOnlyDestinationCoverage.gt(0) &&\n destinationDisplayUsdRate &&\n destinationDisplayUsdRate.gt(0)\n ? displayOnlyDestinationCoverage.mul(destinationDisplayUsdRate)\n : undefined;\n const displayOnlyDestinationSourceUsd =\n displayOnlyDestinationSourceAmount &&\n displayOnlyDestinationSourceAmount.gt(0) &&\n destinationDisplayUsdRate &&\n destinationDisplayUsdRate.gt(0)\n ? displayOnlyDestinationSourceAmount.mul(destinationDisplayUsdRate)\n : undefined;\n\n const intentSourceUsdValues = normalizedIntentSources.map((source) =>\n parseDecimal(source.value),\n );\n const intentSourceUsdNumber =\n normalizedIntentSources.length > 0\n ? intentSourceUsdValues.every((value) => value !== undefined)\n ? intentSourceUsdValues.reduce(\n (sum, value) => sum.plus(value ?? 0),\n new Decimal(0),\n )\n : parseDecimal(fromAmountUsd)\n : parseDecimal(fromAmountUsd);\n const effectiveSourceUsdNumber =\n displayOnlyDestinationCoverageUsd !== undefined\n ? (intentSourceUsdNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationCoverageUsd,\n )\n : intentSourceUsdNumber;\n\n const destinationUsdNumber = hasResolvedQuote\n ? isExactOutDisplayFlow\n ? (parseDecimal(toAmountUsd) ?? parseDecimal(normalizedIntentDest?.value))\n : (parseDecimal(normalizedIntentDest?.value) ?? parseDecimal(toAmountUsd))\n : undefined;\n const hasFiatQuote =\n effectiveSourceUsdNumber !== undefined &&\n destinationUsdNumber !== undefined &&\n effectiveSourceUsdNumber.gt(0) &&\n destinationUsdNumber.gt(0);\n\n const bridgeFees = intentData?.feesAndBuffer?.bridge;\n const bridgeFeeData =\n bridgeFees && typeof bridgeFees === \"object\" ? bridgeFees : undefined;\n const bridgeTotalNumber =\n typeof bridgeFees === \"string\"\n ? parseDecimal(bridgeFees)\n : parseDecimal(bridgeFeeData?.total);\n const collectionFeeNumber = parseDecimal(bridgeFeeData?.collection);\n const fulfilmentFeeNumber = parseDecimal(bridgeFeeData?.fulfilment);\n const executionGasFeeNumber =\n parseDecimal(bridgeFeeData?.caGas) ??\n (collectionFeeNumber !== undefined || fulfilmentFeeNumber !== undefined\n ? (collectionFeeNumber ?? new Decimal(0)).plus(\n fulfilmentFeeNumber ?? new Decimal(0),\n )\n : undefined);\n const protocolFeeNumber = parseDecimal(bridgeFeeData?.protocol);\n const solverFeeNumber = parseDecimal(bridgeFeeData?.solver);\n const bridgeGasSuppliedNumber = parseDecimal(bridgeFeeData?.gasSupplied);\n const destinationGasValueNumber =\n parseDecimal(normalizedIntentDest?.gas?.value) ??\n parseDecimal(destinationGasFeeUsd);\n const destinationGasSuppliedNumber =\n bridgeGasSuppliedNumber ?? destinationGasValueNumber;\n const bridgeTotalWithDestinationGas =\n bridgeTotalNumber &&\n !bridgeGasSuppliedNumber &&\n destinationGasValueNumber &&\n destinationGasValueNumber.gt(0)\n ? bridgeTotalNumber.plus(destinationGasValueNumber)\n : bridgeTotalNumber;\n const swapBufferNumber = parseDecimal(intentData?.feesAndBuffer?.buffer);\n const bridgeComponentsTotalNumber = bridgeFeeData\n ? [\n executionGasFeeNumber,\n protocolFeeNumber,\n solverFeeNumber,\n destinationGasSuppliedNumber,\n ].reduce(\n (sum, value) => sum.plus(value ?? new Decimal(0)),\n new Decimal(0),\n )\n : undefined;\n const explicitFeeNumber =\n bridgeTotalWithDestinationGas ??\n (bridgeComponentsTotalNumber && bridgeComponentsTotalNumber.gt(0)\n ? bridgeComponentsTotalNumber\n : undefined) ??\n parseDecimal(totalFeeUsd) ??\n parseDecimal((intentData as any)?.fees?.total) ??\n destinationGasSuppliedNumber;\n const feeNumber =\n explicitFeeNumber ?? (hasFiatQuote ? new Decimal(0) : undefined);\n const quotedDestinationUsdNumber = parseDecimal(normalizedIntentDest?.value);\n const exactOutPaidUsdNumber = (() => {\n if (!isExactOutDisplayFlow) return effectiveSourceUsdNumber;\n\n const candidates = [\n effectiveSourceUsdNumber,\n requestedDestinationUsd,\n ].filter((value): value is Decimal => Boolean(value && value.gt(0)));\n\n if (requestedDestinationUsd && requestedDestinationUsd.gt(0)) {\n if (\n intentSourceUsdNumber &&\n intentSourceUsdNumber.gt(0) &&\n quotedDestinationUsdNumber &&\n quotedDestinationUsdNumber.gt(0)\n ) {\n candidates.push(\n requestedDestinationUsd.plus(\n Decimal.max(\n intentSourceUsdNumber.minus(quotedDestinationUsdNumber),\n 0,\n ),\n ),\n );\n }\n\n const knownOverhead = (feeNumber ?? new Decimal(0)).plus(\n swapBufferNumber ?? new Decimal(0),\n );\n if (knownOverhead.gt(0)) {\n candidates.push(requestedDestinationUsd.plus(knownOverhead));\n }\n }\n\n return candidates.reduce(\n (max, value) => (!max || value.gt(max) ? value : max),\n undefined,\n );\n })();\n const quoteImpactUsd =\n hasFiatQuote && feeNumber !== undefined\n ? Decimal.max(\n effectiveSourceUsdNumber\n .minus(destinationUsdNumber)\n .minus(feeNumber)\n .minus(swapBufferNumber ?? new Decimal(0)),\n 0,\n )\n : undefined;\n const priceImpactUsd =\n quoteImpactUsd ?? parseDecimal((intentData as any)?.priceImpactUsd);\n const computedSwapImpactPercent =\n hasFiatQuote && priceImpactUsd !== undefined\n ? priceImpactUsd.eq(0)\n ? new Decimal(0)\n : effectiveSourceUsdNumber !== undefined &&\n effectiveSourceUsdNumber.gt(0)\n ? priceImpactUsd.neg().div(effectiveSourceUsdNumber).mul(100)\n : undefined\n : undefined;\n const swapImpactPercent =\n computedSwapImpactPercent ??\n parseDecimal((intentData as any)?.swapImpactPercent) ??\n parseDecimal((intentData as any)?.priceImpactPercent);\n\n const destinationTokenAmount =\n isExactOutDisplayFlow && (toAmountTokens || toAmount)\n ? toAmountTokens || toAmount || \"0\"\n : normalizedIntentDest?.amount || toAmountTokens || toAmount || \"0\";\n const feeDetailRows = bridgeFeeData\n ? [\n {\n label: \"Execution Gas Fee\",\n value: executionGasFeeNumber ?? new Decimal(0),\n },\n {\n label: \"Protocol Fee\",\n value: protocolFeeNumber ?? new Decimal(0),\n },\n {\n label: \"Solver Fee\",\n value: solverFeeNumber ?? new Decimal(0),\n },\n ...(destinationGasSuppliedNumber && destinationGasSuppliedNumber.gt(0)\n ? [{ label: \"Gas Sponsorship\", value: destinationGasSuppliedNumber }]\n : []),\n ]\n : destinationGasSuppliedNumber && destinationGasSuppliedNumber.gt(0)\n ? [\n ...(feeNumber && feeNumber.gt(destinationGasSuppliedNumber)\n ? [\n {\n label: \"Network & protocol\",\n value: feeNumber.minus(destinationGasSuppliedNumber),\n },\n ]\n : []),\n { label: \"Gas Sponsorship\", value: destinationGasSuppliedNumber },\n ]\n : feeNumber !== undefined\n ? [{ label: \"Network & protocol\", value: feeNumber }]\n : [];\n\n const pendingLabel = isLoading ? \"Fetching quote\" : \"Quote unavailable\";\n const pendingValue = isLoading ? \"...\" : \"--\";\n const sourceUsd =\n exactOutPaidUsdNumber !== undefined\n ? `${formatAmount(exactOutPaidUsdNumber)} USD`\n : pendingValue;\n const receiveUsd = hasFiatQuote\n ? `${formatAmount(destinationUsdNumber)} USD`\n : pendingValue;\n const feeUsd =\n feeNumber !== undefined ? formatUsdAmount(feeNumber) : pendingValue;\n const impactUsd =\n priceImpactUsd !== undefined\n ? formatUsdDelta(priceImpactUsd)\n : pendingValue;\n const impactPercent =\n swapImpactPercent !== undefined\n ? `${formatAmount(swapImpactPercent, {\n min: 2,\n max: 2,\n })}%`\n : pendingValue;\n const destinationHeaderAmount = hasResolvedQuote\n ? formatHeaderTokenAmount(destinationTokenAmount)\n : pendingValue;\n const destinationTokenDisplay = hasResolvedQuote\n ? `${formatTokenAmount(destinationTokenAmount)} ${destTokenSymbol}`\n : pendingLabel;\n const destinationSourceAddress =\n normalizedIntentDest?.token.contractAddress || toToken?.contractAddress;\n const destinationSourceKey = getSourceDisplayKey(\n normalizedIntentDest?.chain.id ?? toToken?.chainId,\n destinationSourceAddress,\n destTokenSymbol,\n );\n const hasDestinationSourceRow = Boolean(\n destinationSourceKey &&\n (normalizedIntentSources.length > 0\n ? normalizedIntentSources.some((source) => {\n const sourceKey = getSourceDisplayKey(\n source.chain.id,\n source.token.contractAddress,\n source.token.symbol,\n );\n return sourceKey === destinationSourceKey;\n })\n : fallbackSources.some((source) => {\n const sourceKey = getSourceDisplayKey(\n source.chainId ?? \"\",\n source.contractAddress,\n source.symbol,\n );\n return sourceKey === destinationSourceKey;\n })),\n );\n const swapBufferDisplay =\n swapBufferNumber !== undefined\n ? formatUsdValue(swapBufferNumber)\n : pendingValue;\n const baseSourceDetailRows =\n normalizedIntentSources.length > 0\n ? normalizedIntentSources.map((source, index) => {\n const fallbackSource = fallbackSources.find(\n (token) =>\n token.chainId === source.chain.id &&\n (token.contractAddress?.toLowerCase() ===\n source.token.contractAddress?.toLowerCase() ||\n token.symbol === source.token.symbol),\n );\n\n const sourceKey = getSourceDisplayKey(\n source.chain.id,\n source.token.contractAddress,\n source.token.symbol,\n );\n const isDestinationSource =\n sourceKey === destinationSourceKey &&\n displayOnlyDestinationSourceAmount !== undefined;\n const sourceAmountNumber = parseDecimal(source.amount);\n const displaySourceAmount =\n isDestinationSource && displayOnlyDestinationSourceAmount\n ? (sourceAmountNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationSourceAmount,\n )\n : sourceAmountNumber;\n const sourceValueNumber = parseDecimal(source.value);\n const displaySourceUsd =\n isDestinationSource && displayOnlyDestinationSourceUsd\n ? (sourceValueNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationSourceUsd,\n )\n : sourceValueNumber;\n const tokenAmountValue =\n displaySourceAmount !== undefined\n ? formatTokenAmount(displaySourceAmount)\n : formatTokenAmount(source.amount);\n\n return {\n key: `${source.chain.id}-${source.token.contractAddress}-${index}`,\n tokenLogo: source.token.logo || fallbackSource?.logo || \"\",\n chainLogo: source.chain.logo || fallbackSource?.chainLogo || \"\",\n symbol: source.token.symbol,\n chainName: getShortChainName(source.chain.id, source.chain.name),\n tokenAmount: `${tokenAmountValue} ${source.token.symbol}`,\n tokenAmountValue,\n usdAmount:\n displaySourceUsd !== undefined\n ? formatUsdValue(displaySourceUsd)\n : pendingValue,\n index,\n };\n })\n : fallbackSources.map((source, index) => {\n const sourceAmount =\n source.userAmount ||\n (fallbackSources.length === 1 ? fromAmount : \"\");\n const sourceKey = getSourceDisplayKey(\n source.chainId ?? \"\",\n source.contractAddress,\n source.symbol,\n );\n const isDestinationSource =\n sourceKey === destinationSourceKey &&\n displayOnlyDestinationSourceAmount !== undefined;\n const sourceAmountNumber = parseDecimal(sourceAmount);\n const displaySourceAmount =\n isDestinationSource && displayOnlyDestinationSourceAmount\n ? (sourceAmountNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationSourceAmount,\n )\n : sourceAmountNumber;\n const sourceUsdNumber =\n source.balanceInFiat && source.balance\n ? toDecimal(source.userAmount || 0).mul(\n toDecimal(source.balanceInFiat).div(\n Decimal.max(toDecimal(source.balance), 1),\n ),\n )\n : undefined;\n const displaySourceUsd =\n isDestinationSource && displayOnlyDestinationSourceUsd\n ? (sourceUsdNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationSourceUsd,\n )\n : sourceUsdNumber;\n const tokenAmountValue =\n displaySourceAmount !== undefined\n ? formatTokenAmount(displaySourceAmount)\n : \"\";\n\n return {\n key: `${source.chainId ?? \"chain\"}-${source.contractAddress}-${index}`,\n tokenLogo: source.logo || \"\",\n chainLogo: source.chainLogo || \"\",\n symbol: source.symbol,\n chainName: getShortChainName(source.chainId, source.chainName),\n tokenAmount: tokenAmountValue\n ? `${tokenAmountValue} ${source.symbol}`\n : pendingLabel,\n tokenAmountValue,\n usdAmount:\n displaySourceUsd !== undefined\n ? formatUsdValue(displaySourceUsd)\n : pendingValue,\n index,\n };\n });\n const displayOnlyDestinationSourceRow =\n displayOnlyDestinationSourceAmount &&\n displayOnlyDestinationSourceAmount.gt(0) &&\n !hasDestinationSourceRow\n ? {\n key: `destination-existing-${normalizedIntentDest?.chain.id ?? toToken?.chainId ?? \"chain\"}-${normalizedIntentDest?.token.contractAddress ?? toToken?.contractAddress ?? \"token\"}`,\n tokenLogo: normalizedIntentDest?.token.logo || toToken?.logo || \"\",\n chainLogo:\n normalizedIntentDest?.chain.logo || toToken?.chainLogo || \"\",\n symbol: destTokenSymbol,\n chainName: getShortChainName(\n normalizedIntentDest?.chain.id ?? toToken?.chainId,\n normalizedIntentDest?.chain.name || toToken?.chainName || \"\",\n ),\n tokenAmount: `${formatTokenAmount(displayOnlyDestinationSourceAmount)} ${destTokenSymbol}`,\n tokenAmountValue: formatTokenAmount(\n displayOnlyDestinationSourceAmount,\n ),\n usdAmount:\n displayOnlyDestinationSourceUsd !== undefined\n ? formatUsdValue(displayOnlyDestinationSourceUsd)\n : pendingValue,\n index: baseSourceDetailRows.length,\n }\n : undefined;\n const sourceDetailRows = sortSourceDetailRowsByUsdDesc(\n displayOnlyDestinationSourceRow\n ? [...baseSourceDetailRows, displayOnlyDestinationSourceRow]\n : baseSourceDetailRows,\n );\n const sourceSymbols = (() => {\n const symbols =\n sourceDetailRows.length > 0\n ? sourceDetailRows.map((source) => source.symbol)\n : baseSourceSymbols;\n return destTokenSymbol && symbols.includes(destTokenSymbol)\n ? unique([\n destTokenSymbol,\n ...symbols.filter((symbol) => symbol !== destTokenSymbol),\n ])\n : unique(symbols);\n })();\n const sourceLabel = formatSymbolSummary(sourceSymbols);\n const sourceAssetCount =\n sourceDetailRows.length || baseSourceAssetCount || sourceSymbols.length;\n const singleSourceHeader = (() => {\n if (displayOnlyDestinationSourceRow) return null;\n if (\n !displayOnlyDestinationSourceRow &&\n normalizedIntentSources.length === 1\n ) {\n const source = normalizedIntentSources[0];\n const sourceRow = baseSourceDetailRows[0];\n return {\n amount:\n sourceRow?.tokenAmountValue ?? formatHeaderTokenAmount(source.amount),\n chainName: getShortChainName(source.chain.id, source.chain.name),\n symbol: source.token.symbol,\n };\n }\n\n if (normalizedIntentSources.length === 0 && fallbackSources.length === 1) {\n const source = fallbackSources[0];\n const sourceAmount = source.userAmount || fromAmount;\n if (!sourceAmount) return null;\n return {\n amount:\n baseSourceDetailRows[0]?.tokenAmountValue ??\n formatHeaderTokenAmount(sourceAmount),\n chainName: getShortChainName(source.chainId, source.chainName),\n symbol: source.symbol,\n };\n }\n\n return null;\n })();\n const sourceHeaderAmount =\n isExactOutDisplayFlow && exactOutPaidUsdNumber !== undefined\n ? formatAmount(exactOutPaidUsdNumber)\n : singleSourceHeader?.amount ||\n (exactOutPaidUsdNumber !== undefined\n ? formatAmount(exactOutPaidUsdNumber)\n : pendingValue);\n const sourceHeaderUnit =\n isExactOutDisplayFlow && exactOutPaidUsdNumber !== undefined\n ? \"USD\"\n : singleSourceHeader?.symbol || \"USD\";\n const sourceHeaderSubtitle = (() => {\n if (isExactOutDisplayFlow && exactOutPaidUsdNumber !== undefined) {\n const count = sourceAssetCount || 1;\n return `${count} asset${count === 1 ? \"\" : \"s\"}`;\n }\n\n if (singleSourceHeader) {\n return singleSourceHeader.chainName\n ? `on ${singleSourceHeader.chainName}`\n : \"\";\n }\n\n const count = sourceAssetCount || 1;\n return `${count} asset${count === 1 ? \"\" : \"s\"}`;\n })();\n // The preview panel owns vertical scrolling; nested source scrollbars make\n // confirm screens show multiple scrollbars.\n const shouldScrollSourceDetails = false;\n const progressExplorerUrls = explorerUrls ?? {\n destinationExplorerUrl: null,\n sourceExplorerUrl: null,\n };\n const progressSources = sourceDetailRows.map((source) => ({\n chainLogo: source.chainLogo,\n symbol: source.symbol,\n tokenLogo: source.tokenLogo,\n }));\n const primarySourceForProgress = progressSources[0] ?? {\n chainLogo: fromToken?.chainLogo ?? \"\",\n symbol: sourceSymbols[0] ?? \"\",\n tokenLogo: fromToken?.logo ?? \"\",\n };\n const destinationProgressLogos = {\n chain: normalizedIntentDest?.chain.logo || toToken?.chainLogo || \"\",\n token: normalizedIntentDest?.token.logo || toToken?.logo || \"\",\n };\n\n const ctaLabel =\n flowMode === \"deposit\"\n ? \"Deposit now\"\n : flowMode === \"send\" || hasRecipientTransfer\n ? \"Send now\"\n : \"Swap now\";\n const shouldPulseCta =\n !isLoading && !isRefreshing && !isExecuting && !quoteUnavailable;\n const shouldShowMayanBadge = intentData?.bridgeProvider === \"mayan\";\n\n return (\n
\n \n \n \n
\n \n {sourceHeaderAmount}\n \n {sourceHeaderUnit}\n \n
\n \n {sourceHeaderSubtitle}\n
\n \n\n \n {[0, 1, 2, 3, 4].map((index) => (\n \n ))}\n \n\n \n \n {destinationHeaderAmount}\n \n {destTokenSymbol}\n \n \n \n {destChainName ? `on ${destChainName}` : destTokenSymbol}\n \n \n \n\n {singleSourceHeader ? (\n \n ) : (\n \n {\n startTransition();\n setShowSourceDetails((value) => !value);\n }}\n />\n \n )}\n\n {!singleSourceHeader && (\n \n {sourceDetailRows.length > 0 ? (\n \n \n {sourceDetailRows.map((source) => (\n \n \n \n \n {source.chainLogo && (\n \n )}\n \n \n \n {source.symbol}\n \n \n on {source.chainName || \"Unknown chain\"}\n \n \n \n \n \n {source.tokenAmount}\n \n {!isExactOutDisplayFlow && (\n \n {source.usdAmount}\n \n )}\n \n \n ))}\n \n {shouldScrollSourceDetails && (\n {\n sourceDetailsScrollRef.current?.scrollBy({\n behavior: \"smooth\",\n top: 54,\n });\n }}\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${border}`,\n borderRadius: \"999px\",\n boxShadow: \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n bottom: \"4px\",\n cursor: \"pointer\",\n display: \"flex\",\n height: \"20px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"20px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n ) : (\n \n \n {pendingLabel}\n \n \n )}\n \n )}\n\n \n\n {hasRecipientTransfer && recipientAddress && (\n \n )}\n\n \n {\n startTransition();\n setShowFeeDetails((value) => !value);\n }}\n />\n \n\n \n {feeDetailRows.length > 0 ? (\n feeDetailRows.map((row) => (\n \n \n {row.label}\n \n \n {formatUsdValue(row.value)}\n \n \n ))\n ) : (\n \n \n Network & protocol\n \n \n {pendingValue}\n \n \n )}\n \n\n \n {\n startTransition();\n setShowImpactDetails((value) => !value);\n }}\n />\n \n\n \n \n \n Swap Impact\n \n \n {impactPercent}\n \n \n \n \n Max. Slippage\n \n \n Auto\n \n \n \n\n {shouldShowSwapBuffer && (\n \n Swap Buffer\n \n \n }\n value={swapBufferDisplay}\n />\n )}\n \n\n {isExecuting && steps && steps.length > 0 && (\n \n 1}\n isTransferMode={hasRecipientTransfer}\n sourceLogos={{\n chain: primarySourceForProgress.chainLogo,\n token: primarySourceForProgress.tokenLogo,\n }}\n sourceSymbol={primarySourceForProgress.symbol}\n sources={progressSources.length > 1 ? progressSources : undefined}\n steps={steps}\n />\n \n )}\n\n {shouldShowMayanBadge && }\n\n \n {isExecuting ? (\n isDepositMode ? (\n \"Depositing...\"\n ) : isSendMode || hasRecipientTransfer ? (\n \"Sending...\"\n ) : (\n \"Swapping...\"\n )\n ) : isLoading ? (\n \n ) : isRefreshing ? (\n \"Refreshing quotes...\"\n ) : quoteUnavailable ? (\n pendingLabel\n ) : (\n ctaLabel\n )}\n \n \n );\n}\n", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\n\"use client\";\n\nimport Decimal from \"decimal.js\";\nimport { ChevronDown, Info, Loader2 } from \"lucide-react\";\nimport React, { useRef, useState } from \"react\";\nimport { parseAmount as parseDecimal } from \"../utils/amount\";\nimport type { SwapStepType } from \"../../common/types/transaction-flow\";\nimport { CHAIN_METADATA, getShortChainName } from \"../../common/utils/constant\";\nimport TransactionProgress from \"../../swaps/components/transaction-progress\";\nimport { Button } from \"../../ui/button\";\nimport {\n type NexusWidgetDepositOpportunityMetadata,\n type NexusWidgetMode,\n} from \"../types\";\nimport { NEXUS_WIDGET_FAST_SPINNER_STYLE } from \"../theme\";\nimport { type SwapTokenOption } from \"./swap-asset-selector\";\n\nexport interface SwapIntentSource {\n amount: string;\n chain: { id: number; logo: string; name: string };\n token: {\n contractAddress: string;\n decimals: number;\n logo?: string;\n symbol: string;\n };\n value?: string;\n}\n\nexport interface SwapIntentDestination {\n amount: string;\n chain: { id: number; logo: string; name: string };\n gas: {\n amount: string;\n value?: string;\n token: {\n contractAddress: string;\n decimals: number;\n logo?: string;\n symbol: string;\n };\n };\n token: {\n contractAddress: string;\n decimals: number;\n logo?: string;\n symbol: string;\n };\n value?: string;\n}\n\nexport type BridgeProvider = \"nexus\" | \"mayan\" | null;\n\nexport interface SwapIntentData {\n bridgeProvider?: BridgeProvider;\n destination: SwapIntentDestination;\n feesAndBuffer?: {\n buffer?: string;\n bridge?:\n | {\n caGas?: string;\n collection?: string;\n fulfilment?: string;\n gasSupplied?: string;\n protocol?: string;\n solver?: string;\n total?: string;\n }\n | string\n | null;\n };\n sources: SwapIntentSource[];\n}\n\nexport interface SwapIntentPreviewProps {\n activeMode?: NexusWidgetMode;\n estimatedTime?: string;\n explorerUrls?: {\n sourceExplorerUrl: string | null;\n destinationExplorerUrl: string | null;\n };\n fromAmount: string;\n fromAmountUsd?: string;\n destinationGasFeeUsd?: string;\n fromToken?: SwapTokenOption;\n fromTokens?: SwapTokenOption[];\n intentData?: SwapIntentData | null;\n isExecuting?: boolean;\n isLoading?: boolean;\n isRefreshing?: boolean;\n mode?: NexusWidgetMode;\n onAccept: () => void;\n onReject: () => void;\n onTransitionChange?: (isTransitioning: boolean) => void;\n opportunity?: NexusWidgetDepositOpportunityMetadata;\n recipientAddress?: string;\n steps?: Array<{ id: number; completed: boolean; step: SwapStepType }>;\n supportedTokenAssets?: any[] | null;\n swapBalances?: any[] | null;\n swapType?: \"exactIn\" | \"exactOut\";\n toAmount?: string;\n toAmountTokens?: string;\n toAmountUsd?: string;\n toToken?: SwapTokenOption;\n totalFeeUsd?: string;\n}\n\nconst fontFamily = '\"Geist\", var(--font-geist-sans), system-ui, sans-serif';\nconst primary = \"var(--nexus-widget-text-strong, #161615)\";\nconst muted = \"var(--nexus-widget-text-secondary, #848483)\";\nconst border = \"var(--nexus-widget-border, #E8E8E7)\";\nconst brand = \"var(--foreground-brand)\";\n\nconst toDecimal = (value: unknown) => parseDecimal(value) ?? new Decimal(0);\n\nconst formatAmount = (\n value: unknown,\n options: { min?: number; max?: number } = {},\n) => {\n const amount = toDecimal(value);\n const max = options.max ?? 2;\n return amount.toDecimalPlaces(max).toFixed();\n};\n\nconst formatUsdDelta = (value: Decimal) => {\n if (value.gt(0) && value.lt(0.01)) return \"-<0.01 USD\";\n return value.gt(0) ? `-${formatAmount(value)} USD` : \"0 USD\";\n};\n\nconst formatUsdAmount = (value: Decimal) => {\n if (value.gt(0) && value.lt(0.01)) return \"<0.01 USD\";\n return value.gt(0) ? `${formatAmount(value)} USD` : \"0 USD\";\n};\n\nconst formatUsdValue = (value: Decimal) => {\n const absolute = value.abs();\n if (absolute.eq(0)) return \"$0\";\n if (absolute.lt(0.01)) return value.lt(0) ? \"-<$0.01\" : \"<$0.01\";\n\n const amount = formatAmount(absolute, { max: 2 });\n\n return value.lt(0) ? `-$${amount}` : `$${amount}`;\n};\n\nconst formatTokenAmount = (value: unknown) => {\n const amount = toDecimal(value);\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst formatHeaderTokenAmount = (value: unknown) => {\n const amount = toDecimal(value);\n if (amount.isZero()) return \"0\";\n if (amount.abs().gte(1000)) {\n return amount.toDecimalPlaces(2).toFixed();\n }\n if (amount.abs().gte(1)) {\n return amount.toDecimalPlaces(4).toFixed();\n }\n return amount.toDecimalPlaces(8).toFixed();\n};\n\nconst getFontSize = (amountStr: string, symbolStr: string) => {\n const totalLength =\n String(amountStr || \"\").length + String(symbolStr || \"\").length;\n if (totalLength > 16) return \"13px\";\n if (totalLength > 12) return \"15px\";\n return \"17px\";\n};\n\nconst unique = (values: string[]) =>\n Array.from(new Set(values.filter(Boolean)));\n\nconst isNativeTokenAddress = (address?: string) => {\n const lower = (address ?? \"\").toLowerCase();\n return (\n !lower ||\n lower === \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\" ||\n lower === \"0x0000000000000000000000000000000000000000\"\n );\n};\n\nconst getSourceDisplayKey = (\n chainId?: number | string,\n address?: string,\n symbol?: string,\n) => {\n const chainKey = chainId ?? \"\";\n const normalizedAddress = address?.toLowerCase();\n return normalizedAddress\n ? `${chainKey}-${normalizedAddress}`\n : `${chainKey}-symbol-${(symbol ?? \"\").toUpperCase()}`;\n};\n\nconst normalizeIntentToken = <\n T extends {\n contractAddress?: string;\n decimals?: number;\n logo?: string;\n symbol?: string;\n },\n>(\n token: T | undefined,\n chainId?: number,\n) => {\n const chainMeta = chainId ? CHAIN_METADATA[chainId] : undefined;\n const shouldUseNative =\n isNativeTokenAddress(token?.contractAddress) && Boolean(chainMeta);\n const symbol =\n shouldUseNative && chainMeta?.nativeCurrency.symbol\n ? chainMeta.nativeCurrency.symbol\n : token?.symbol || chainMeta?.nativeCurrency.symbol || \"-\";\n const decimals =\n shouldUseNative && chainMeta?.nativeCurrency.decimals !== undefined\n ? chainMeta.nativeCurrency.decimals\n : (token?.decimals ?? chainMeta?.nativeCurrency.decimals ?? 18);\n\n return {\n contractAddress: token?.contractAddress ?? \"\",\n decimals,\n logo: token?.logo || (shouldUseNative ? chainMeta?.logo : undefined),\n symbol,\n };\n};\n\nconst formatSymbolSummary = (symbols: string[]) => {\n const visible = unique(symbols);\n if (visible.length === 0) return \"-\";\n if (visible.length <= 2) return visible.join(\", \");\n if (visible.length === 3)\n return `${visible[0]}, ${visible[1]} and ${visible[2]}`;\n\n const others = visible.length - 2;\n return `${visible[0]}, ${visible[1]} and ${others} other${others === 1 ? \"\" : \"s\"}`;\n};\n\nconst sortSourceDetailRowsByUsdDesc = <\n T extends { symbol?: string; usdAmount?: string },\n>(\n rows: T[],\n) =>\n [...rows].sort((a, b) => {\n const usdDelta = toDecimal(b.usdAmount).cmp(toDecimal(a.usdAmount));\n if (usdDelta !== 0) return usdDelta;\n return (a.symbol ?? \"\").localeCompare(b.symbol ?? \"\");\n });\n\nfunction IntentLogo({\n src,\n alt,\n label,\n size,\n fontSize,\n outline,\n style,\n}: {\n src?: string;\n alt?: string;\n label?: string;\n size: number;\n fontSize: number;\n outline?: string;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n React.useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n const fallbackLabel = (label || alt || \"?\").trim().slice(0, 1).toUpperCase();\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n backgroundColor: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n height: `${size}px`,\n objectFit: \"cover\",\n outline,\n width: `${size}px`,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {fallbackLabel || \"?\"}\n \n );\n}\n\nfunction DetailToggle({\n expanded,\n onClick,\n}: {\n expanded: boolean;\n onClick: () => void;\n}) {\n return (\n \n {expanded ? \"Hide Details\" : \"View Details\"}\n \n \n );\n}\n\nfunction TruncatedAddress({ address }: { address: string }) {\n const [showTooltip, setShowTooltip] = useState(false);\n const label =\n address.length > 12\n ? `${address.slice(0, 6)}...${address.slice(-4)}`\n : address;\n\n return (\n setShowTooltip(false)}\n onFocus={() => setShowTooltip(true)}\n onMouseEnter={() => setShowTooltip(true)}\n onMouseLeave={() => setShowTooltip(false)}\n style={{\n color: brand,\n display: \"inline-flex\",\n fontFamily,\n fontSize: \"13px\",\n fontWeight: 500,\n lineHeight: \"15px\",\n outline: \"none\",\n position: \"relative\",\n }}\n tabIndex={0}\n >\n {label}\n {showTooltip && (\n \n {address}\n \n )}\n \n );\n}\n\nfunction RecipientRow({ address }: { address: string }) {\n return (\n \n
\n \n Recipient\n
\n \n Wallet address\n \n \n
\n \n
\n \n );\n}\n\nfunction InlineInfoTooltip({ message }: { message: string }) {\n const [showTooltip, setShowTooltip] = useState(false);\n\n return (\n setShowTooltip(false)}\n onFocus={() => setShowTooltip(true)}\n onMouseEnter={() => setShowTooltip(true)}\n onMouseLeave={() => setShowTooltip(false)}\n style={{\n alignItems: \"center\",\n color: muted,\n display: \"inline-flex\",\n lineHeight: 0,\n outline: \"none\",\n position: \"relative\",\n }}\n tabIndex={0}\n >\n \n {showTooltip && (\n \n {message}\n \n )}\n \n );\n}\n\nfunction MayanPoweredBadge() {\n return (\n \n \n This transaction is powered by\n \n \n );\n}\n\nfunction Row({\n title,\n subtitle,\n value,\n secondaryValue,\n children,\n}: {\n title: React.ReactNode;\n subtitle: string;\n value: string;\n secondaryValue?: string;\n children?: React.ReactNode;\n}) {\n return (\n \n
\n \n {title}\n
\n \n {subtitle}\n \n \n \n \n {value}\n \n {secondaryValue ? (\n \n {secondaryValue}\n \n ) : (\n children\n )}\n \n \n );\n}\n\nfunction AnimatedDetails({\n open,\n children,\n background = \"var(--nexus-widget-background, #F9F9F8)\",\n gap = \"9px\",\n padding = \"12px 14px\",\n}: {\n open: boolean;\n children: React.ReactNode;\n background?: string;\n gap?: string;\n padding?: string;\n}) {\n return (\n \n
\n \n {children}\n
\n \n \n );\n}\n\nexport function SwapIntentPreview({\n fromTokens,\n fromToken,\n toToken,\n fromAmount,\n fromAmountUsd,\n destinationGasFeeUsd,\n toAmount,\n toAmountUsd,\n toAmountTokens,\n totalFeeUsd,\n isLoading,\n isRefreshing,\n isExecuting,\n swapType,\n intentData,\n mode,\n opportunity,\n recipientAddress,\n activeMode,\n steps,\n explorerUrls,\n onAccept,\n onTransitionChange,\n}: SwapIntentPreviewProps) {\n const [showSourceDetails, setShowSourceDetails] = useState(false);\n const [showFeeDetails, setShowFeeDetails] = useState(false);\n const [showImpactDetails, setShowImpactDetails] = useState(false);\n const sourceDetailsScrollRef = useRef(null);\n const [transitionTimeoutId, setTransitionTimeoutId] = useState | null>(null);\n\n const startTransition = () => {\n if (onTransitionChange) {\n onTransitionChange(true);\n }\n if (transitionTimeoutId) {\n clearTimeout(transitionTimeoutId);\n }\n const id = setTimeout(() => {\n if (onTransitionChange) {\n onTransitionChange(false);\n }\n setTransitionTimeoutId(null);\n }, 280);\n setTransitionTimeoutId(id);\n };\n\n React.useEffect(() => {\n return () => {\n if (transitionTimeoutId) {\n clearTimeout(transitionTimeoutId);\n }\n };\n }, [transitionTimeoutId]);\n\n const flowMode = mode ?? activeMode ?? \"swap\";\n const isDepositMode = flowMode === \"deposit\";\n const isSendMode = flowMode === \"send\";\n const hasRecipientTransfer = Boolean(recipientAddress) && !isDepositMode;\n const isExactOutDisplayFlow =\n (isDepositMode || isSendMode) && swapType === \"exactOut\";\n const shouldShowSwapBuffer = swapType !== \"exactIn\";\n const intentSources = intentData?.sources ?? [];\n const intentDest = intentData?.destination;\n const normalizedIntentSources = intentSources.map((source) => ({\n ...source,\n token: normalizeIntentToken(source.token, source.chain.id),\n }));\n const normalizedIntentDest = intentDest\n ? {\n ...intentDest,\n token: normalizeIntentToken(intentDest.token, intentDest.chain.id),\n gas: {\n ...intentDest.gas,\n token: normalizeIntentToken(\n intentDest.gas?.token,\n intentDest.chain.id,\n ),\n },\n }\n : undefined;\n const fallbackSources =\n fromTokens && fromTokens.length > 0\n ? fromTokens\n : fromToken\n ? [fromToken]\n : [];\n\n const baseSourceSymbols =\n normalizedIntentSources.length > 0\n ? unique(normalizedIntentSources.map((source) => source.token.symbol))\n : unique(fallbackSources.map((source) => source.symbol));\n const baseSourceAssetCount =\n normalizedIntentSources.length ||\n fallbackSources.length ||\n baseSourceSymbols.length;\n const hasResolvedQuote = Boolean(\n normalizedIntentDest &&\n (normalizedIntentSources.length > 0 || isExactOutDisplayFlow),\n );\n const quoteUnavailable = !isLoading && !hasResolvedQuote;\n\n const destTokenSymbol =\n normalizedIntentDest?.token.symbol ||\n toToken?.symbol ||\n opportunity?.tokenSymbol ||\n \"-\";\n const destChainName =\n flowMode === \"deposit\"\n ? opportunity?.title || opportunity?.protocol || \"App\"\n : getShortChainName(\n normalizedIntentDest?.chain.id ?? toToken?.chainId,\n normalizedIntentDest?.chain.name || toToken?.chainName || \"\",\n );\n\n const requestedDestinationAmount = isExactOutDisplayFlow\n ? parseDecimal(toAmountTokens ?? toAmount)\n : undefined;\n const quotedDestinationAmount = parseDecimal(normalizedIntentDest?.amount);\n const destinationBalanceAmount = parseDecimal(toToken?.balance);\n const displayOnlyDestinationCoverage = (() => {\n if (\n !isExactOutDisplayFlow ||\n !requestedDestinationAmount ||\n requestedDestinationAmount.lte(0) ||\n !destinationBalanceAmount ||\n destinationBalanceAmount.lte(0)\n ) {\n return undefined;\n }\n\n const externallyProducedAmount =\n normalizedIntentSources.length > 0 &&\n quotedDestinationAmount &&\n quotedDestinationAmount.gt(0)\n ? quotedDestinationAmount\n : new Decimal(0);\n const destinationBalanceAmountNeeded = Decimal.max(\n requestedDestinationAmount.minus(externallyProducedAmount),\n 0,\n );\n const coveredAmount = Decimal.min(\n destinationBalanceAmountNeeded,\n destinationBalanceAmount,\n );\n return coveredAmount.gt(0) ? coveredAmount : undefined;\n })();\n const displayOnlyDestinationSourceAmount = displayOnlyDestinationCoverage;\n const requestedDestinationUsd = parseDecimal(toAmountUsd);\n const destinationDisplayUsdRate =\n requestedDestinationAmount &&\n requestedDestinationAmount.gt(0) &&\n requestedDestinationUsd &&\n requestedDestinationUsd.gt(0)\n ? requestedDestinationUsd.div(requestedDestinationAmount)\n : quotedDestinationAmount &&\n quotedDestinationAmount.gt(0) &&\n normalizedIntentDest?.value\n ? (parseDecimal(normalizedIntentDest.value) ?? new Decimal(0)).div(\n quotedDestinationAmount,\n )\n : undefined;\n const displayOnlyDestinationCoverageUsd =\n displayOnlyDestinationCoverage &&\n displayOnlyDestinationCoverage.gt(0) &&\n destinationDisplayUsdRate &&\n destinationDisplayUsdRate.gt(0)\n ? displayOnlyDestinationCoverage.mul(destinationDisplayUsdRate)\n : undefined;\n const displayOnlyDestinationSourceUsd =\n displayOnlyDestinationSourceAmount &&\n displayOnlyDestinationSourceAmount.gt(0) &&\n destinationDisplayUsdRate &&\n destinationDisplayUsdRate.gt(0)\n ? displayOnlyDestinationSourceAmount.mul(destinationDisplayUsdRate)\n : undefined;\n\n const intentSourceUsdValues = normalizedIntentSources.map((source) =>\n parseDecimal(source.value),\n );\n const intentSourceUsdNumber =\n normalizedIntentSources.length > 0\n ? intentSourceUsdValues.every((value) => value !== undefined)\n ? intentSourceUsdValues.reduce(\n (sum, value) => sum.plus(value ?? 0),\n new Decimal(0),\n )\n : parseDecimal(fromAmountUsd)\n : parseDecimal(fromAmountUsd);\n const effectiveSourceUsdNumber =\n displayOnlyDestinationCoverageUsd !== undefined\n ? (intentSourceUsdNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationCoverageUsd,\n )\n : intentSourceUsdNumber;\n\n const destinationUsdNumber = hasResolvedQuote\n ? isExactOutDisplayFlow\n ? (parseDecimal(toAmountUsd) ?? parseDecimal(normalizedIntentDest?.value))\n : (parseDecimal(normalizedIntentDest?.value) ?? parseDecimal(toAmountUsd))\n : undefined;\n const hasFiatQuote =\n effectiveSourceUsdNumber !== undefined &&\n destinationUsdNumber !== undefined &&\n effectiveSourceUsdNumber.gt(0) &&\n destinationUsdNumber.gt(0);\n\n const bridgeFees = intentData?.feesAndBuffer?.bridge;\n const bridgeFeeData =\n bridgeFees && typeof bridgeFees === \"object\" ? bridgeFees : undefined;\n const bridgeTotalNumber =\n typeof bridgeFees === \"string\"\n ? parseDecimal(bridgeFees)\n : parseDecimal(bridgeFeeData?.total);\n const collectionFeeNumber = parseDecimal(bridgeFeeData?.collection);\n const fulfilmentFeeNumber = parseDecimal(bridgeFeeData?.fulfilment);\n const executionGasFeeNumber =\n parseDecimal(bridgeFeeData?.caGas) ??\n (collectionFeeNumber !== undefined || fulfilmentFeeNumber !== undefined\n ? (collectionFeeNumber ?? new Decimal(0)).plus(\n fulfilmentFeeNumber ?? new Decimal(0),\n )\n : undefined);\n const protocolFeeNumber = parseDecimal(bridgeFeeData?.protocol);\n const solverFeeNumber = parseDecimal(bridgeFeeData?.solver);\n const bridgeGasSuppliedNumber = parseDecimal(bridgeFeeData?.gasSupplied);\n const destinationGasValueNumber =\n parseDecimal(normalizedIntentDest?.gas?.value) ??\n parseDecimal(destinationGasFeeUsd);\n const destinationGasSuppliedNumber =\n bridgeGasSuppliedNumber ?? destinationGasValueNumber;\n const bridgeTotalWithDestinationGas =\n bridgeTotalNumber &&\n !bridgeGasSuppliedNumber &&\n destinationGasValueNumber &&\n destinationGasValueNumber.gt(0)\n ? bridgeTotalNumber.plus(destinationGasValueNumber)\n : bridgeTotalNumber;\n const swapBufferNumber = parseDecimal(intentData?.feesAndBuffer?.buffer);\n const bridgeComponentsTotalNumber = bridgeFeeData\n ? [\n executionGasFeeNumber,\n protocolFeeNumber,\n solverFeeNumber,\n destinationGasSuppliedNumber,\n ].reduce(\n (sum, value) => sum.plus(value ?? new Decimal(0)),\n new Decimal(0),\n )\n : undefined;\n const explicitFeeNumber =\n bridgeTotalWithDestinationGas ??\n (bridgeComponentsTotalNumber && bridgeComponentsTotalNumber.gt(0)\n ? bridgeComponentsTotalNumber\n : undefined) ??\n parseDecimal(totalFeeUsd) ??\n parseDecimal((intentData as any)?.fees?.total) ??\n destinationGasSuppliedNumber;\n const feeNumber =\n explicitFeeNumber ?? (hasFiatQuote ? new Decimal(0) : undefined);\n const quotedDestinationUsdNumber = parseDecimal(normalizedIntentDest?.value);\n const exactOutPaidUsdNumber = (() => {\n if (!isExactOutDisplayFlow) return effectiveSourceUsdNumber;\n\n const candidates = [\n effectiveSourceUsdNumber,\n requestedDestinationUsd,\n ].filter((value): value is Decimal => Boolean(value && value.gt(0)));\n\n if (requestedDestinationUsd && requestedDestinationUsd.gt(0)) {\n if (\n intentSourceUsdNumber &&\n intentSourceUsdNumber.gt(0) &&\n quotedDestinationUsdNumber &&\n quotedDestinationUsdNumber.gt(0)\n ) {\n candidates.push(\n requestedDestinationUsd.plus(\n Decimal.max(\n intentSourceUsdNumber.minus(quotedDestinationUsdNumber),\n 0,\n ),\n ),\n );\n }\n\n const knownOverhead = (feeNumber ?? new Decimal(0)).plus(\n swapBufferNumber ?? new Decimal(0),\n );\n if (knownOverhead.gt(0)) {\n candidates.push(requestedDestinationUsd.plus(knownOverhead));\n }\n }\n\n return candidates.reduce(\n (max, value) => (!max || value.gt(max) ? value : max),\n undefined,\n );\n })();\n const quoteImpactUsd =\n hasFiatQuote && feeNumber !== undefined\n ? Decimal.max(\n effectiveSourceUsdNumber\n .minus(destinationUsdNumber)\n .minus(feeNumber)\n .minus(swapBufferNumber ?? new Decimal(0)),\n 0,\n )\n : undefined;\n const priceImpactUsd =\n quoteImpactUsd ?? parseDecimal((intentData as any)?.priceImpactUsd);\n const computedSwapImpactPercent =\n hasFiatQuote && priceImpactUsd !== undefined\n ? priceImpactUsd.eq(0)\n ? new Decimal(0)\n : effectiveSourceUsdNumber !== undefined &&\n effectiveSourceUsdNumber.gt(0)\n ? priceImpactUsd.neg().div(effectiveSourceUsdNumber).mul(100)\n : undefined\n : undefined;\n const swapImpactPercent =\n computedSwapImpactPercent ??\n parseDecimal((intentData as any)?.swapImpactPercent) ??\n parseDecimal((intentData as any)?.priceImpactPercent);\n\n const destinationTokenAmount =\n isExactOutDisplayFlow && (toAmountTokens || toAmount)\n ? toAmountTokens || toAmount || \"0\"\n : normalizedIntentDest?.amount || toAmountTokens || toAmount || \"0\";\n const feeDetailRows = bridgeFeeData\n ? [\n {\n label: \"Execution Gas Fee\",\n value: executionGasFeeNumber ?? new Decimal(0),\n },\n {\n label: \"Protocol Fee\",\n value: protocolFeeNumber ?? new Decimal(0),\n },\n {\n label: \"Solver Fee\",\n value: solverFeeNumber ?? new Decimal(0),\n },\n ...(destinationGasSuppliedNumber && destinationGasSuppliedNumber.gt(0)\n ? [{ label: \"Gas Sponsorship\", value: destinationGasSuppliedNumber }]\n : []),\n ]\n : destinationGasSuppliedNumber && destinationGasSuppliedNumber.gt(0)\n ? [\n ...(feeNumber && feeNumber.gt(destinationGasSuppliedNumber)\n ? [\n {\n label: \"Network & protocol\",\n value: feeNumber.minus(destinationGasSuppliedNumber),\n },\n ]\n : []),\n { label: \"Gas Sponsorship\", value: destinationGasSuppliedNumber },\n ]\n : feeNumber !== undefined\n ? [{ label: \"Network & protocol\", value: feeNumber }]\n : [];\n\n const pendingLabel = isLoading ? \"Fetching quote\" : \"Quote unavailable\";\n const pendingValue = isLoading ? \"...\" : \"--\";\n const sourceUsd =\n exactOutPaidUsdNumber !== undefined\n ? `${formatAmount(exactOutPaidUsdNumber)} USD`\n : pendingValue;\n const receiveUsd = hasFiatQuote\n ? `${formatAmount(destinationUsdNumber)} USD`\n : pendingValue;\n const feeUsd =\n feeNumber !== undefined ? formatUsdAmount(feeNumber) : pendingValue;\n const impactUsd =\n priceImpactUsd !== undefined\n ? formatUsdDelta(priceImpactUsd)\n : pendingValue;\n const impactPercent =\n swapImpactPercent !== undefined\n ? `${formatAmount(swapImpactPercent, {\n min: 2,\n max: 2,\n })}%`\n : pendingValue;\n const destinationHeaderAmount = hasResolvedQuote\n ? formatHeaderTokenAmount(destinationTokenAmount)\n : pendingValue;\n const destinationTokenDisplay = hasResolvedQuote\n ? `${formatTokenAmount(destinationTokenAmount)} ${destTokenSymbol}`\n : pendingLabel;\n const destinationSourceAddress =\n normalizedIntentDest?.token.contractAddress || toToken?.contractAddress;\n const destinationSourceKey = getSourceDisplayKey(\n normalizedIntentDest?.chain.id ?? toToken?.chainId,\n destinationSourceAddress,\n destTokenSymbol,\n );\n const hasDestinationSourceRow = Boolean(\n destinationSourceKey &&\n (normalizedIntentSources.length > 0\n ? normalizedIntentSources.some((source) => {\n const sourceKey = getSourceDisplayKey(\n source.chain.id,\n source.token.contractAddress,\n source.token.symbol,\n );\n return sourceKey === destinationSourceKey;\n })\n : fallbackSources.some((source) => {\n const sourceKey = getSourceDisplayKey(\n source.chainId ?? \"\",\n source.contractAddress,\n source.symbol,\n );\n return sourceKey === destinationSourceKey;\n })),\n );\n const swapBufferDisplay =\n swapBufferNumber !== undefined\n ? formatUsdValue(swapBufferNumber)\n : pendingValue;\n const baseSourceDetailRows =\n normalizedIntentSources.length > 0\n ? normalizedIntentSources.map((source, index) => {\n const fallbackSource = fallbackSources.find(\n (token) =>\n token.chainId === source.chain.id &&\n (token.contractAddress?.toLowerCase() ===\n source.token.contractAddress?.toLowerCase() ||\n token.symbol === source.token.symbol),\n );\n\n const sourceKey = getSourceDisplayKey(\n source.chain.id,\n source.token.contractAddress,\n source.token.symbol,\n );\n const isDestinationSource =\n sourceKey === destinationSourceKey &&\n displayOnlyDestinationSourceAmount !== undefined;\n const sourceAmountNumber = parseDecimal(source.amount);\n const displaySourceAmount =\n isDestinationSource && displayOnlyDestinationSourceAmount\n ? (sourceAmountNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationSourceAmount,\n )\n : sourceAmountNumber;\n const sourceValueNumber = parseDecimal(source.value);\n const displaySourceUsd =\n isDestinationSource && displayOnlyDestinationSourceUsd\n ? (sourceValueNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationSourceUsd,\n )\n : sourceValueNumber;\n const tokenAmountValue =\n displaySourceAmount !== undefined\n ? formatTokenAmount(displaySourceAmount)\n : formatTokenAmount(source.amount);\n\n return {\n key: `${source.chain.id}-${source.token.contractAddress}-${index}`,\n tokenLogo: source.token.logo || fallbackSource?.logo || \"\",\n chainLogo: source.chain.logo || fallbackSource?.chainLogo || \"\",\n symbol: source.token.symbol,\n chainName: getShortChainName(source.chain.id, source.chain.name),\n tokenAmount: `${tokenAmountValue} ${source.token.symbol}`,\n tokenAmountValue,\n usdAmount:\n displaySourceUsd !== undefined\n ? formatUsdValue(displaySourceUsd)\n : pendingValue,\n index,\n };\n })\n : fallbackSources.map((source, index) => {\n const sourceAmount =\n source.userAmount ||\n (fallbackSources.length === 1 ? fromAmount : \"\");\n const sourceKey = getSourceDisplayKey(\n source.chainId ?? \"\",\n source.contractAddress,\n source.symbol,\n );\n const isDestinationSource =\n sourceKey === destinationSourceKey &&\n displayOnlyDestinationSourceAmount !== undefined;\n const sourceAmountNumber = parseDecimal(sourceAmount);\n const displaySourceAmount =\n isDestinationSource && displayOnlyDestinationSourceAmount\n ? (sourceAmountNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationSourceAmount,\n )\n : sourceAmountNumber;\n const sourceUsdNumber =\n source.balanceInFiat && source.balance\n ? toDecimal(source.userAmount || 0).mul(\n toDecimal(source.balanceInFiat).div(\n Decimal.max(toDecimal(source.balance), 1),\n ),\n )\n : undefined;\n const displaySourceUsd =\n isDestinationSource && displayOnlyDestinationSourceUsd\n ? (sourceUsdNumber ?? new Decimal(0)).plus(\n displayOnlyDestinationSourceUsd,\n )\n : sourceUsdNumber;\n const tokenAmountValue =\n displaySourceAmount !== undefined\n ? formatTokenAmount(displaySourceAmount)\n : \"\";\n\n return {\n key: `${source.chainId ?? \"chain\"}-${source.contractAddress}-${index}`,\n tokenLogo: source.logo || \"\",\n chainLogo: source.chainLogo || \"\",\n symbol: source.symbol,\n chainName: getShortChainName(source.chainId, source.chainName),\n tokenAmount: tokenAmountValue\n ? `${tokenAmountValue} ${source.symbol}`\n : pendingLabel,\n tokenAmountValue,\n usdAmount:\n displaySourceUsd !== undefined\n ? formatUsdValue(displaySourceUsd)\n : pendingValue,\n index,\n };\n });\n const displayOnlyDestinationSourceRow =\n displayOnlyDestinationSourceAmount &&\n displayOnlyDestinationSourceAmount.gt(0) &&\n !hasDestinationSourceRow\n ? {\n key: `destination-existing-${normalizedIntentDest?.chain.id ?? toToken?.chainId ?? \"chain\"}-${normalizedIntentDest?.token.contractAddress ?? toToken?.contractAddress ?? \"token\"}`,\n tokenLogo: normalizedIntentDest?.token.logo || toToken?.logo || \"\",\n chainLogo:\n normalizedIntentDest?.chain.logo || toToken?.chainLogo || \"\",\n symbol: destTokenSymbol,\n chainName: getShortChainName(\n normalizedIntentDest?.chain.id ?? toToken?.chainId,\n normalizedIntentDest?.chain.name || toToken?.chainName || \"\",\n ),\n tokenAmount: `${formatTokenAmount(displayOnlyDestinationSourceAmount)} ${destTokenSymbol}`,\n tokenAmountValue: formatTokenAmount(\n displayOnlyDestinationSourceAmount,\n ),\n usdAmount:\n displayOnlyDestinationSourceUsd !== undefined\n ? formatUsdValue(displayOnlyDestinationSourceUsd)\n : pendingValue,\n index: baseSourceDetailRows.length,\n }\n : undefined;\n const sourceDetailRows = sortSourceDetailRowsByUsdDesc(\n displayOnlyDestinationSourceRow\n ? [...baseSourceDetailRows, displayOnlyDestinationSourceRow]\n : baseSourceDetailRows,\n );\n const sourceSymbols = (() => {\n const symbols =\n sourceDetailRows.length > 0\n ? sourceDetailRows.map((source) => source.symbol)\n : baseSourceSymbols;\n return destTokenSymbol && symbols.includes(destTokenSymbol)\n ? unique([\n destTokenSymbol,\n ...symbols.filter((symbol) => symbol !== destTokenSymbol),\n ])\n : unique(symbols);\n })();\n const sourceLabel = formatSymbolSummary(sourceSymbols);\n const sourceAssetCount =\n sourceDetailRows.length || baseSourceAssetCount || sourceSymbols.length;\n const singleSourceHeader = (() => {\n if (displayOnlyDestinationSourceRow) return null;\n if (\n !displayOnlyDestinationSourceRow &&\n normalizedIntentSources.length === 1\n ) {\n const source = normalizedIntentSources[0];\n const sourceRow = baseSourceDetailRows[0];\n return {\n amount:\n sourceRow?.tokenAmountValue ?? formatHeaderTokenAmount(source.amount),\n chainName: getShortChainName(source.chain.id, source.chain.name),\n symbol: source.token.symbol,\n };\n }\n\n if (normalizedIntentSources.length === 0 && fallbackSources.length === 1) {\n const source = fallbackSources[0];\n const sourceAmount = source.userAmount || fromAmount;\n if (!sourceAmount) return null;\n return {\n amount:\n baseSourceDetailRows[0]?.tokenAmountValue ??\n formatHeaderTokenAmount(sourceAmount),\n chainName: getShortChainName(source.chainId, source.chainName),\n symbol: source.symbol,\n };\n }\n\n return null;\n })();\n const sourceHeaderAmount =\n isExactOutDisplayFlow && exactOutPaidUsdNumber !== undefined\n ? formatAmount(exactOutPaidUsdNumber)\n : singleSourceHeader?.amount ||\n (exactOutPaidUsdNumber !== undefined\n ? formatAmount(exactOutPaidUsdNumber)\n : pendingValue);\n const sourceHeaderUnit =\n isExactOutDisplayFlow && exactOutPaidUsdNumber !== undefined\n ? \"USD\"\n : singleSourceHeader?.symbol || \"USD\";\n const sourceHeaderSubtitle = (() => {\n if (isExactOutDisplayFlow && exactOutPaidUsdNumber !== undefined) {\n const count = sourceAssetCount || 1;\n return `${count} asset${count === 1 ? \"\" : \"s\"}`;\n }\n\n if (singleSourceHeader) {\n return singleSourceHeader.chainName\n ? `on ${singleSourceHeader.chainName}`\n : \"\";\n }\n\n const count = sourceAssetCount || 1;\n return `${count} asset${count === 1 ? \"\" : \"s\"}`;\n })();\n // The preview panel owns vertical scrolling; nested source scrollbars make\n // confirm screens show multiple scrollbars.\n const shouldScrollSourceDetails = false;\n const progressExplorerUrls = explorerUrls ?? {\n destinationExplorerUrl: null,\n sourceExplorerUrl: null,\n };\n const progressSources = sourceDetailRows.map((source) => ({\n chainLogo: source.chainLogo,\n symbol: source.symbol,\n tokenLogo: source.tokenLogo,\n }));\n const primarySourceForProgress = progressSources[0] ?? {\n chainLogo: fromToken?.chainLogo ?? \"\",\n symbol: sourceSymbols[0] ?? \"\",\n tokenLogo: fromToken?.logo ?? \"\",\n };\n const destinationProgressLogos = {\n chain: normalizedIntentDest?.chain.logo || toToken?.chainLogo || \"\",\n token: normalizedIntentDest?.token.logo || toToken?.logo || \"\",\n };\n\n const ctaLabel =\n flowMode === \"deposit\"\n ? \"Deposit now\"\n : flowMode === \"send\" || hasRecipientTransfer\n ? \"Send now\"\n : \"Swap now\";\n const shouldPulseCta =\n !isLoading && !isRefreshing && !isExecuting && !quoteUnavailable;\n const shouldShowMayanBadge =\n !isDepositMode && intentData?.bridgeProvider === \"mayan\";\n\n return (\n
\n \n \n \n
\n \n {sourceHeaderAmount}\n \n {sourceHeaderUnit}\n \n
\n \n {sourceHeaderSubtitle}\n
\n \n\n \n {[0, 1, 2, 3, 4].map((index) => (\n \n ))}\n \n\n \n \n {destinationHeaderAmount}\n \n {destTokenSymbol}\n \n \n \n {destChainName ? `on ${destChainName}` : destTokenSymbol}\n \n \n \n\n {singleSourceHeader ? (\n \n ) : (\n \n {\n startTransition();\n setShowSourceDetails((value) => !value);\n }}\n />\n \n )}\n\n {!singleSourceHeader && (\n \n {sourceDetailRows.length > 0 ? (\n \n \n {sourceDetailRows.map((source) => (\n \n \n \n \n {source.chainLogo && (\n \n )}\n \n \n \n {source.symbol}\n \n \n on {source.chainName || \"Unknown chain\"}\n \n \n \n \n \n {source.tokenAmount}\n \n {!isExactOutDisplayFlow && (\n \n {source.usdAmount}\n \n )}\n \n \n ))}\n \n {shouldScrollSourceDetails && (\n {\n sourceDetailsScrollRef.current?.scrollBy({\n behavior: \"smooth\",\n top: 54,\n });\n }}\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${border}`,\n borderRadius: \"999px\",\n boxShadow: \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n bottom: \"4px\",\n cursor: \"pointer\",\n display: \"flex\",\n height: \"20px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"20px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n ) : (\n \n \n {pendingLabel}\n \n \n )}\n \n )}\n\n \n\n {hasRecipientTransfer && recipientAddress && (\n \n )}\n\n \n {\n startTransition();\n setShowFeeDetails((value) => !value);\n }}\n />\n \n\n \n {feeDetailRows.length > 0 ? (\n feeDetailRows.map((row) => (\n \n \n {row.label}\n \n \n {formatUsdValue(row.value)}\n \n \n ))\n ) : (\n \n \n Network & protocol\n \n \n {pendingValue}\n \n \n )}\n \n\n \n {\n startTransition();\n setShowImpactDetails((value) => !value);\n }}\n />\n \n\n \n \n \n Swap Impact\n \n \n {impactPercent}\n \n \n \n \n Max. Slippage\n \n \n Auto\n \n \n \n\n {shouldShowSwapBuffer && (\n \n Swap Buffer\n \n \n }\n value={swapBufferDisplay}\n />\n )}\n \n\n {isExecuting && steps && steps.length > 0 && (\n \n 1}\n isTransferMode={hasRecipientTransfer}\n sourceLogos={{\n chain: primarySourceForProgress.chainLogo,\n token: primarySourceForProgress.tokenLogo,\n }}\n sourceSymbol={primarySourceForProgress.symbol}\n sources={progressSources.length > 1 ? progressSources : undefined}\n steps={steps}\n />\n \n )}\n\n {shouldShowMayanBadge && }\n\n \n {isExecuting ? (\n isDepositMode ? (\n \"Depositing...\"\n ) : isSendMode || hasRecipientTransfer ? (\n \"Sending...\"\n ) : (\n \"Swapping...\"\n )\n ) : isLoading ? (\n \n ) : isRefreshing ? (\n \"Refreshing quotes...\"\n ) : quoteUnavailable ? (\n pendingLabel\n ) : (\n ctaLabel\n )}\n \n \n );\n}\n", "type": "registry:component", "target": "components/nexus/components/swap-intent-preview.tsx" }, { "path": "registry/avail-widgets/nexus-widget/nexus-widget.tsx", - "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\"use client\";\n\nimport {\n ERROR_CODES,\n type EthereumProvider,\n} from \"@avail-project/nexus-core\";\nimport Decimal from \"decimal.js\";\nimport { AlertCircle, ArrowLeft, ChevronDown, Loader2 } from \"lucide-react\";\nimport React, {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport {\n createPublicClient,\n encodeFunctionData,\n erc20Abi,\n http,\n isAddress,\n parseUnits,\n zeroAddress,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\nimport { normalize } from \"viem/ens\";\nimport {\n useAccount,\n useConnect,\n useConnectorClient,\n usePublicClient,\n useWalletClient,\n} from \"wagmi\";\nimport { ErrorBoundary } from \"../common/components/ErrorBoundary\";\nimport { useTransactionSteps } from \"../common/tx/useTransactionSteps\";\nimport type {\n BridgeStepType,\n SwapStepType,\n} from \"../common/types/transaction-flow\";\nimport {\n CHAIN_METADATA,\n getShortChainName,\n isSwapSupportedBySdkChainList,\n SUPPORTED_CHAINS,\n TOKEN_CONTRACT_ADDRESSES,\n TOKEN_METADATA,\n} from \"../common/utils/constant\";\nimport { type UserAsset, useNexus } from \"../nexus/NexusProvider\";\nimport { Button } from \"../ui/button\";\nimport { Dialog, DialogContent, DialogTrigger } from \"../ui/dialog\";\nimport { DepositIdleForm } from \"./components/deposit-idle-form\";\nimport {\n type NexusWidgetProgressEvent,\n NexusWidgetProgressScreen,\n} from \"./components/nexus-widget-progress-screen\";\nimport {\n getCachedReceiveTokenMatch,\n preloadReceiveTokens,\n ReceiveAssetSelector,\n} from \"./components/receive-asset-selector\";\nimport { RecipientInput } from \"./components/recipient-input\";\nimport { SendIdleForm } from \"./components/send-idle-form\";\nimport { StatusAlert } from \"./components/status-alerts\";\nimport {\n deriveTokenOptions,\n SwapAssetSelector,\n type SwapTokenOption,\n} from \"./components/swap-asset-selector\";\nimport { SwapIdleForm } from \"./components/swap-idle-form\";\nimport {\n type BridgeProvider,\n type SwapIntentData,\n type SwapIntentDestination,\n type SwapIntentSource,\n SwapIntentPreview,\n} from \"./components/swap-intent-preview\";\nimport {\n NEXUS_WIDGET_DEFAULT_PRIMARY_COLOR,\n getNexusWidgetThemeStyle,\n nexusWidgetTheme,\n nexusWidgetInteractionStyles,\n resolveNexusWidgetTheme,\n} from \"./theme\";\nimport {\n NexusWidgetThemeContext,\n useNexusWidgetThemeStyle,\n useResolvedNexusWidgetTheme,\n} from \"./theme-context\";\nimport {\n type NexusWidgetAppearance,\n type NexusWidgetConfig,\n type NexusWidgetDepositConfig,\n type NexusWidgetDestination,\n type NexusWidgetDestinationToken,\n type NexusWidgetDepositOpportunityConfig,\n type NexusWidgetDepositOpportunityMetadata,\n type NexusWidgetMode,\n type NexusWidgetPrefillToken,\n type NexusWidgetProps,\n type NexusWidgetRuntimePrefill,\n type SwapType,\n} from \"./types\";\nimport {\n parseAmount as parseDecimalLoose,\n parseAmount as parseFiatNumber,\n} from \"./utils/amount\";\nimport { findCitreaReceiveToken } from \"./utils/citrea-tokens\";\nimport {\n type DepositSourceFilter,\n getDepositSourceId,\n resolveDepositSourceSelection,\n} from \"./utils/deposit-source-selection\";\n\n// ---------------------------------------------------------------------------\n// Types for swap step machine\n// ---------------------------------------------------------------------------\n\ntype SwapStep =\n | \"idle\" // main screen\n | \"choose-swap-asset\" // pick source token\n | \"choose-receive-asset\" // pick receive token\n | \"enter-recipient\" // pick recipient (send mode)\n | \"preview-intent\" // intent preview card\n | \"progress\" // transaction in flight\n | \"success\" // completed seamlessly\n | \"failed\" // failed swap receipt\n | \"history\"; // transaction history\n\ntype SourceFilterTab = \"all\" | \"native\" | \"stables\" | \"custom\";\n\ntype SwapHistoryStatus =\n | \"pending\"\n | \"fulfilled\"\n | \"failed\"\n | \"timeout\"\n | \"refund-initiated\";\n\ninterface SwapHistoryEntry {\n autoRefundAvailable?: boolean;\n createdAt: number;\n durationSeconds?: number;\n endedAt?: number;\n error?: string;\n failedStepType?: string;\n failureDescription?: string;\n failureMessage?: string;\n feeUsd?: string;\n finalExplorerUrl?: string | null;\n fromTokens: SwapTokenOption[];\n id: string;\n intentData: SwapIntentData | null;\n intentExplorerUrl?: string | null;\n intentId?: number;\n mode: NexusWidgetMode;\n opportunity?: NexusWidgetDepositOpportunityMetadata;\n recipientAddress?: string;\n requestedToAmount?: string;\n requestedToValue?: string;\n sourceExplorerUrl?: string | null;\n startedAt: number;\n status: SwapHistoryStatus;\n toToken?: SwapTokenOption;\n}\n\ntype HistorySourceRow = {\n amount: string;\n chainId?: number;\n chainLogo?: string;\n chainName: string;\n contractAddress?: string;\n key: string;\n symbol: string;\n tokenLogo?: string;\n value?: unknown;\n};\n\ntype SwapQuoteIssue = {\n type: \"insufficientSources\";\n message: string;\n missingUsd?: string;\n};\n\ntype ReceiveAmountIssue = {\n ctaLabel: string;\n message: string;\n type: \"configuredAmountLimit\" | \"receiveLimitExceeded\" | \"unpricedReceiveToken\";\n};\n\ntype CachedIntentUsdRate = {\n amount: string;\n rate: string;\n updatedAt: number;\n value: string;\n};\n\ntype PredictiveQuote = {\n key: string;\n mode: \"exactIn\" | \"exactOut\";\n sources?: SwapTokenOption[];\n toAmount?: string;\n toUsd?: string;\n};\n\ntype IntentFetchTiming = {\n background: boolean;\n endTimeMs?: number;\n fetchDurationMs?: number;\n operation: string;\n quoteInputKey: string;\n runId: number;\n sourceCount?: number;\n startTimeMs: number;\n walletAddress?: string | null;\n};\n\ntype PredictiveQuoteBaseline = {\n destinationUsdRate: string;\n exactInDestinationAmountPerSourceUsd?: string;\n exactOutSourceUsdPerDestinationUsd?: string;\n updatedAt: number;\n};\n\nconst DESTINATION_RECEIVE_LIMIT_USD_BY_CHAIN_ID: Record = {\n [SUPPORTED_CHAINS.MEGAETH]: 10_000,\n [SUPPORTED_CHAINS.CITREA]: 2000,\n [SUPPORTED_CHAINS.SCROLL]: 500,\n};\n\nconst QUOTE_REFRESH_INTERVAL_MS = 30000;\nconst EXACT_OUT_INPUT_DEBOUNCE_MS = 1300;\nconst DRAWER_CLOSE_MS = 220;\nconst BALANCE_REFRESH_AFTER_TERMINAL_MS = 3000;\nconst MODAL_HEIGHT_TRANSITION_MS = 220;\nconst ROOT_HEIGHT_TRANSITION_MS = 140;\nconst ASSET_SELECTOR_DRAWER_HEIGHT = \"90%\";\nconst TOKEN_SELECTOR_MIN_ROOT_CONTENT_HEIGHT = 620;\nconst CONFIGURED_RECEIVE_SELECTOR_BASE_HEIGHT = 170;\nconst CONFIGURED_RECEIVE_SELECTOR_ROW_HEIGHT = 62;\nconst BASIS_POINTS = 10000;\nconst PREDICTIVE_EXACT_IN_DISCOUNT_BPS = 50;\nconst PREDICTIVE_EXACT_OUT_DESTINATION_BUFFER_PCT = 0.1;\nconst PREDICTIVE_EXACT_OUT_DESTINATION_BUFFER_MAX_USD = 2;\nconst PREDICTIVE_EXACT_OUT_SOURCE_BUFFER_PCT = 0.02;\nconst PREDICTIVE_EXACT_OUT_SOURCE_BUFFER_MAX_USD = 1;\nconst PREDICTIVE_QUOTE_DISPLAY_DECIMALS = 8;\nconst DEPOSIT_TOKEN_DISPLAY_DECIMALS = 8;\nconst ETHEREUM_MAINNET_CHAIN_ID = 1;\nconst SDK_EXACT_OUT_STABLE_SYMBOLS = new Set([\n \"USDC\",\n \"USDT\",\n \"DAI\",\n \"BUSD\",\n \"TUSD\",\n \"FRAX\",\n \"LUSD\",\n \"USDD\",\n \"USDP\",\n \"GUSD\",\n]);\nconst SWAP_HISTORY_STORAGE_KEY_PREFIX = \"nexus-widget-transaction-history-v1\";\nconst TIMEOUT_LABEL = \"Timed Out\";\nconst PROGRESS_EVENT_NAMES = {\n BRIDGE_PLAN_LIST: \"bridge_plan_list\",\n BRIDGE_PLAN_PROGRESS: \"bridge_plan_progress\",\n SWAP_PLAN_LIST: \"swap_plan_list\",\n SWAP_PLAN_PROGRESS: \"swap_plan_progress\",\n} as const;\nconst PLAN_FINAL_STATES = new Set([\"completed\", \"confirmed\", \"submitted\"]);\nconst PLAN_STEP_FUNDS_MAY_HAVE_MOVED_STATES = new Set([\n \"completed\",\n \"confirmed\",\n \"submitted\",\n \"failed\",\n]);\nconst theme = nexusWidgetTheme;\nconst tooltipSurface = \"var(--nexus-widget-surface-raised, #FFFFFE)\";\nconst tooltipText = theme.colors.textStrong;\nconst tooltipBorder = theme.colors.border;\nconst uiFont = theme.fonts.sans;\nconst modalHeightTransitionStyle = {\n interpolateSize: \"allow-keywords\",\n} as React.CSSProperties;\n\nconst getCappedTokenDisplayDecimals = (decimals?: number) => {\n const parsedDecimals = Number(decimals);\n if (!Number.isFinite(parsedDecimals) || parsedDecimals < 0) {\n return DEPOSIT_TOKEN_DISPLAY_DECIMALS;\n }\n return Math.min(Math.floor(parsedDecimals), DEPOSIT_TOKEN_DISPLAY_DECIMALS);\n};\nconst modalHeightTransition = `height ${MODAL_HEIGHT_TRANSITION_MS}ms ease, max-height ${MODAL_HEIGHT_TRANSITION_MS}ms ease`;\n\nconst normalizeSdkExactOutStableSymbol = (symbol?: string) =>\n (symbol ?? \"\")\n .trim()\n .toUpperCase()\n .replaceAll(\"\\u20ae\", \"T\")\n .replaceAll(/[^A-Z0-9]/g, \"\");\n\nconst isSdkExactOutStableSymbol = (symbol?: string) =>\n SDK_EXACT_OUT_STABLE_SYMBOLS.has(normalizeSdkExactOutStableSymbol(symbol));\n\nconst applyPredictiveExactOutBufferUsd = (\n amount: Decimal,\n pct: number,\n maxUsd: number\n) => Decimal.min(amount.mul(pct), new Decimal(maxUsd));\n\nconst getPredictiveExactOutSourceTargetUsd = (\n destinationUsdNeedingSources: Decimal,\n cachedSourceUsdRatio?: Decimal\n) => {\n if (destinationUsdNeedingSources.lte(0)) return new Decimal(0);\n if (cachedSourceUsdRatio?.gt(0)) {\n return destinationUsdNeedingSources.mul(cachedSourceUsdRatio);\n }\n\n const destinationBuffer = applyPredictiveExactOutBufferUsd(\n destinationUsdNeedingSources,\n PREDICTIVE_EXACT_OUT_DESTINATION_BUFFER_PCT,\n PREDICTIVE_EXACT_OUT_DESTINATION_BUFFER_MAX_USD\n );\n const destinationBuffered = destinationUsdNeedingSources.plus(\n destinationBuffer\n );\n const sourceBuffer = applyPredictiveExactOutBufferUsd(\n destinationBuffered,\n PREDICTIVE_EXACT_OUT_SOURCE_BUFFER_PCT,\n PREDICTIVE_EXACT_OUT_SOURCE_BUFFER_MAX_USD\n );\n\n return destinationBuffered.plus(sourceBuffer);\n};\n\nconst getSwapHistoryStorageKey = (ownerAddress?: string) =>\n `${SWAP_HISTORY_STORAGE_KEY_PREFIX}:${ownerAddress?.toLowerCase() || \"anonymous\"}`;\n\nconst getTokenSelectionKey = (token?: SwapTokenOption | null) => {\n if (!token) return \"\";\n if (token.isUnified) {\n return `unified:${token.unifiedSymbol ?? token.symbol}`;\n }\n return `${token.chainId ?? \"unknown\"}:${token.contractAddress.toLowerCase()}`;\n};\n\nconst getDisplaySourceTokenKey = (token?: SwapTokenOption | null) => {\n if (!token) return \"\";\n const chainId = token.chainId ?? \"unknown\";\n const address = token.contractAddress?.toLowerCase();\n return address\n ? `${chainId}:${address}`\n : `${chainId}:symbol:${token.symbol.toUpperCase()}`;\n};\n\nconst sumDecimalStrings = (left?: string, right?: string) => {\n const leftAmount = parseDecimalLoose(left) ?? new Decimal(0);\n const rightAmount = parseDecimalLoose(right) ?? new Decimal(0);\n const sum = leftAmount.plus(rightAmount);\n return sum.gt(0) ? sum.toFixed() : undefined;\n};\n\nconst mergeDisplaySourceTokens = (tokens: SwapTokenOption[]) => {\n const merged = new Map();\n\n for (const token of tokens) {\n const key = getDisplaySourceTokenKey(token);\n if (!key) continue;\n const existing = merged.get(key);\n if (!existing) {\n merged.set(key, token);\n continue;\n }\n\n const userAmount = sumDecimalStrings(\n existing.userAmount || existing.balance,\n token.userAmount || token.balance\n );\n const userAmountUsd = sumDecimalStrings(\n existing.userAmountUsd || existing.balanceInFiat,\n token.userAmountUsd || token.balanceInFiat\n );\n\n merged.set(key, {\n ...existing,\n balance: userAmount ?? existing.balance,\n balanceInFiat: userAmountUsd ?? existing.balanceInFiat,\n chainLogo: existing.chainLogo || token.chainLogo,\n logo: existing.logo || token.logo,\n userAmount: userAmount ?? existing.userAmount,\n userAmountUsd: userAmountUsd ?? existing.userAmountUsd,\n });\n }\n\n return Array.from(merged.values());\n};\n\nconst getTokenQuoteKey = (token?: SwapTokenOption | null) => {\n if (!token) return \"\";\n return [\n getTokenSelectionKey(token),\n token.symbol ?? \"\",\n token.decimals ?? \"\",\n ].join(\":\");\n};\n\nconst getSourceTokensQuoteKey = (tokens: SwapTokenOption[]) =>\n tokens\n .filter((token) => {\n const amt = token.userAmount ?? \"\";\n const cleaned = amt.replaceAll(/[^0-9.]/g, \"\");\n const num = Number.parseFloat(cleaned);\n return !Number.isNaN(num) && num > 0;\n })\n .map((token) =>\n [\n getTokenSelectionKey(token),\n token.symbol ?? \"\",\n token.decimals ?? \"\",\n token.userAmount ?? \"\",\n token.userAmountUsd ?? \"\",\n token.userAmountMode ?? \"\",\n ].join(\":\")\n )\n .join(\"|\");\n\nconst getSourceTokenSyncKey = (token: SwapTokenOption) =>\n [\n getTokenSelectionKey(token),\n token.userAmount ?? \"\",\n token.userAmountUsd ?? \"\",\n token.balance ?? \"\",\n token.balanceInFiat ?? \"\",\n ].join(\":\");\n\nconst getSourceTokenListSyncKey = (tokens: SwapTokenOption[]) =>\n tokens.map(getSourceTokenSyncKey).join(\"|\");\n\nconst isSameTokenSelection = (\n a?: SwapTokenOption | null,\n b?: SwapTokenOption | null\n) => Boolean(a && b && getTokenSelectionKey(a) === getTokenSelectionKey(b));\n\nconst getDepositConfigIdentity = (deposit?: NexusWidgetDepositOpportunityMetadata | null) => {\n if (!deposit) return \"\";\n return [\n deposit.chainId,\n deposit.tokenAddress.toLowerCase(),\n deposit.tokenSymbol,\n deposit.tokenDecimals,\n deposit.protocol ?? \"\",\n deposit.title ?? \"\",\n ].join(\":\");\n};\n\nconst isSameDepositConfig = (\n a?: NexusWidgetDepositOpportunityConfig | null,\n b?: NexusWidgetDepositOpportunityConfig | null\n) => {\n if (!a || !b) return false;\n return getDepositConfigIdentity(a) === getDepositConfigIdentity(b);\n};\n\nconst getConfiguredReceiveSelectorRootHeight = (tokenCount: number) => {\n if (tokenCount <= 0) return TOKEN_SELECTOR_MIN_ROOT_CONTENT_HEIGHT;\n const visibleRows = Math.min(Math.max(tokenCount, 1), 6);\n return Math.min(\n TOKEN_SELECTOR_MIN_ROOT_CONTENT_HEIGHT,\n Math.ceil(\n (CONFIGURED_RECEIVE_SELECTOR_BASE_HEIGHT +\n visibleRows * CONFIGURED_RECEIVE_SELECTOR_ROW_HEIGHT) /\n 0.9\n )\n );\n};\n\nconst getConfiguredDeposit = (\n config: RuntimeNexusWidgetConfig\n): NexusWidgetDepositOpportunityConfig | undefined => config.deposit ?? config.deposits?.[0];\n\ntype RuntimeDestinationPair = {\n chain: number;\n decimals?: number;\n logo?: string;\n symbol?: string;\n token: `0x${string}`;\n};\n\ntype RuntimeNexusWidgetAppearance = NexusWidgetAppearance & {\n logoUrl?: string;\n themeMode?: \"auto\" | \"light\" | \"dark\";\n widgetHeading?: string;\n};\n\ntype RuntimeNexusWidgetConfig = {\n allowedDestinationChains?: number[];\n allowedDestinationPairs?: RuntimeDestinationPair[];\n allowedSourcePairs?: RuntimeDestinationPair[];\n appearance?: RuntimeNexusWidgetAppearance;\n deposit?: NexusWidgetDepositOpportunityConfig;\n deposits?: NexusWidgetDepositOpportunityConfig[];\n mode: NexusWidgetMode;\n prefill?: NexusWidgetRuntimePrefill;\n};\n\ntype RuntimeNexusWidgetAmountInput = {\n max?: string;\n min?: string;\n mode: \"fixed\" | \"user\";\n value?: string;\n};\n\ntype NormalizedNexusWidgetConfig = {\n activeMode: NexusWidgetMode;\n amountInput?: RuntimeNexusWidgetAmountInput;\n appearance?: RuntimeNexusWidgetAppearance;\n config: RuntimeNexusWidgetConfig;\n depositOptions: NexusWidgetDepositOpportunityConfig[];\n isAmountFixed: boolean;\n isRecipientLocked: boolean;\n};\n\nconst normalizeConfiguredString = (value: unknown) => {\n if (value === null || value === undefined) return undefined;\n const text = String(value).trim();\n return text || undefined;\n};\n\nconst normalizeConfiguredAddress = (value: unknown) => {\n const text = normalizeConfiguredString(value);\n return text && isAddress(text) ? text : undefined;\n};\n\nconst isPositiveGasLimit = (value: unknown): value is bigint =>\n typeof value === \"bigint\" && value > BigInt(0);\n\nconst normalizePositiveNumericString = (value: unknown) => {\n const text = normalizeConfiguredString(value);\n if (!text) return undefined;\n try {\n const decimal = new Decimal(text);\n return decimal.isFinite() && decimal.gt(0) ? text : undefined;\n } catch {\n return undefined;\n }\n};\n\nconst normalizeNonNegativeNumericString = (value: unknown) => {\n const text = normalizeConfiguredString(value);\n if (!text) return undefined;\n try {\n const decimal = new Decimal(text);\n return decimal.isFinite() && decimal.gte(0) ? text : undefined;\n } catch {\n return undefined;\n }\n};\n\nconst normalizeHttpUrlString = (value: unknown) => {\n const text = normalizeConfiguredString(value);\n if (!text) return undefined;\n return /^https?:\\/\\//i.test(text) ? text : undefined;\n};\n\nconst normalizeNexusWidgetPrimaryColor = (value?: string) => {\n return normalizeConfiguredString(value);\n};\n\nconst expandHexColor = (value: string) => {\n const text = value.trim();\n if (/^#[0-9a-fA-F]{6}$/.test(text)) return text;\n if (/^#[0-9a-fA-F]{3}$/.test(text)) {\n const [r, g, b] = text.slice(1);\n return `#${r}${r}${g}${g}${b}${b}`;\n }\n return undefined;\n};\n\nconst parseNumberComponent = (value: string, max: number) => {\n const text = value.trim();\n if (!text) return undefined;\n if (text.endsWith(\"%\")) {\n const percent = Number.parseFloat(text.slice(0, -1));\n return Number.isFinite(percent)\n ? Math.max(0, Math.min(max, (percent / 100) * max))\n : undefined;\n }\n const parsed = Number.parseFloat(text);\n return Number.isFinite(parsed) ? Math.max(0, Math.min(max, parsed)) : undefined;\n};\n\nconst parseAngleComponent = (value: string) => {\n const parsed = Number.parseFloat(value.trim());\n if (!Number.isFinite(parsed)) return undefined;\n return ((parsed % 360) + 360) % 360;\n};\n\nconst hslToRgb = (h: number, s: number, l: number): [number, number, number] => {\n const saturation = Math.max(0, Math.min(100, s)) / 100;\n const lightness = Math.max(0, Math.min(100, l)) / 100;\n const c = (1 - Math.abs(2 * lightness - 1)) * saturation;\n const hp = h / 60;\n const x = c * (1 - Math.abs((hp % 2) - 1));\n let r1 = 0;\n let g1 = 0;\n let b1 = 0;\n if (hp >= 0 && hp < 1) {\n r1 = c;\n g1 = x;\n } else if (hp >= 1 && hp < 2) {\n r1 = x;\n g1 = c;\n } else if (hp >= 2 && hp < 3) {\n g1 = c;\n b1 = x;\n } else if (hp >= 3 && hp < 4) {\n g1 = x;\n b1 = c;\n } else if (hp >= 4 && hp < 5) {\n r1 = x;\n b1 = c;\n } else {\n r1 = c;\n b1 = x;\n }\n const m = lightness - c / 2;\n return [\n Math.round((r1 + m) * 255),\n Math.round((g1 + m) * 255),\n Math.round((b1 + m) * 255),\n ];\n};\n\nconst parseCssColorToRgb = (\n color: string,\n allowBrowserResolution = true\n): [number, number, number] | undefined => {\n const text = normalizeConfiguredString(color);\n if (!text) return undefined;\n\n const hex = expandHexColor(text);\n if (hex) {\n return [\n Number.parseInt(hex.slice(1, 3), 16),\n Number.parseInt(hex.slice(3, 5), 16),\n Number.parseInt(hex.slice(5, 7), 16),\n ];\n }\n\n const rgbMatch = text.match(/^rgba?\\((.*)\\)$/i);\n if (rgbMatch) {\n const parts = rgbMatch[1].trim().split(/[\\s,\\/]+/).filter(Boolean);\n if (parts.length >= 3) {\n const r = parseNumberComponent(parts[0], 255);\n const g = parseNumberComponent(parts[1], 255);\n const b = parseNumberComponent(parts[2], 255);\n if (r !== undefined && g !== undefined && b !== undefined) {\n return [Math.round(r), Math.round(g), Math.round(b)];\n }\n }\n }\n\n const hslMatch = text.match(/^hsla?\\((.*)\\)$/i);\n if (hslMatch) {\n const parts = hslMatch[1].trim().split(/[\\s,\\/]+/).filter(Boolean);\n if (parts.length >= 3) {\n const h = parseAngleComponent(parts[0]);\n const s = parseNumberComponent(parts[1], 100);\n const l = parseNumberComponent(parts[2], 100);\n if (h !== undefined && s !== undefined && l !== undefined) {\n return hslToRgb(h, s, l);\n }\n }\n }\n\n if (allowBrowserResolution && typeof document !== \"undefined\") {\n const canvas = document.createElement(\"canvas\");\n const context = canvas.getContext(\"2d\");\n if (context) {\n const baseline = \"#010203\";\n context.fillStyle = baseline;\n context.fillStyle = text;\n const resolved = String(context.fillStyle);\n if (resolved !== baseline || text.toLowerCase() === baseline) {\n return parseCssColorToRgb(resolved, false);\n }\n }\n }\n\n return undefined;\n};\n\nconst getReadableTextColor = (background: string) => {\n const rgb = parseCssColorToRgb(background);\n if (!rgb) return \"#FFFFFE\";\n const [rValue, gValue, bValue] = rgb;\n const r = rValue / 255;\n const g = gValue / 255;\n const b = bValue / 255;\n const linear = [r, g, b].map((channel) =>\n channel <= 0.03928\n ? channel / 12.92\n : Math.pow((channel + 0.055) / 1.055, 2.4)\n );\n const luminance = 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];\n return luminance > 0.54 ? \"#161615\" : \"#FFFFFE\";\n};\n\nconst normalizeNexusWidgetAmountInput = (\n config: NexusWidgetConfig\n): RuntimeNexusWidgetAmountInput | undefined => {\n if (config.mode === \"swap\") return undefined;\n const value = normalizePositiveNumericString(\n \"amount\" in (config.prefill ?? {}) ? config.prefill?.amount : undefined\n );\n const min = normalizeNonNegativeNumericString(config.validation?.minAmount);\n const max = normalizePositiveNumericString(config.validation?.maxAmount);\n return value || min || max ? { mode: \"user\", value, min, max } : undefined;\n};\n\nconst normalizeNexusWidgetAppearance = (\n appearance?: NexusWidgetAppearance\n): RuntimeNexusWidgetAppearance | undefined => {\n if (!appearance) return undefined;\n const appName = normalizeConfiguredString(appearance.appName);\n const appLogoURL = normalizeHttpUrlString(appearance.appLogoURL);\n const heading = normalizeConfiguredString(appearance.heading);\n const mode =\n appearance.mode === \"dark\" || appearance.mode === \"light\"\n ? appearance.mode\n : \"system\";\n const primaryColor = normalizeConfiguredString(appearance.primaryColor);\n return {\n ...appearance,\n appLogoURL,\n appName,\n heading,\n logoUrl: appLogoURL,\n mode,\n primaryColor,\n themeMode: mode === \"system\" ? \"auto\" : mode,\n widgetHeading: heading,\n };\n};\n\nconst normalizeConfiguredChainId = (value: unknown) => {\n const chainId = Number(value);\n return Number.isFinite(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nconst getConfiguredDestinationChainId = (\n destination?: NexusWidgetDestination\n) => normalizeConfiguredChainId(destination?.chain);\n\nconst getConfiguredDestinationTokenSymbol = (\n token: NexusWidgetDestinationToken\n) => normalizeConfiguredString(token.symbol);\n\nconst getConfiguredDestinationTokenAddress = (\n token: NexusWidgetDestinationToken\n) => normalizeConfiguredAddress(token.address);\n\nconst toSwapTokenOptionFromConfiguredDestinationToken = (\n token: NexusWidgetDestinationToken,\n chainId: number\n): SwapTokenOption | undefined => {\n const contractAddress = getConfiguredDestinationTokenAddress(token);\n const symbol = getConfiguredDestinationTokenSymbol(token);\n if (!contractAddress || !symbol) return undefined;\n const chainMeta = CHAIN_METADATA[chainId];\n return {\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n chainId,\n chainLogo: chainMeta?.logo,\n chainName: getShortChainName(chainId, chainMeta?.name ?? `Chain ${chainId}`),\n contractAddress,\n decimals: token.decimals ?? 18,\n logo: token.logo ?? \"\",\n name: symbol,\n symbol,\n };\n};\n\nconst toSwapTokenOptionFromDepositConfig = (\n deposit: NexusWidgetDepositOpportunityConfig\n): SwapTokenOption => {\n const chainMeta = CHAIN_METADATA[deposit.chainId];\n return {\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n chainId: deposit.chainId,\n chainLogo: chainMeta?.logo,\n chainName: getShortChainName(\n deposit.chainId,\n chainMeta?.name ?? `Chain ${deposit.chainId}`\n ),\n contractAddress: deposit.tokenAddress,\n decimals: deposit.tokenDecimals,\n logo: deposit.tokenLogo || deposit.logo || \"\",\n name: deposit.tokenSymbol,\n symbol: deposit.tokenSymbol,\n };\n};\n\nconst applyNexusWidgetAppearanceToDeposit = (\n deposit: NexusWidgetDepositOpportunityConfig,\n appearance?: RuntimeNexusWidgetAppearance\n): NexusWidgetDepositOpportunityConfig => {\n const appName = normalizeConfiguredString(appearance?.appName);\n const logoUrl = normalizeConfiguredString(appearance?.logoUrl);\n if (!appName && !logoUrl) return deposit;\n return {\n ...deposit,\n depositTargetLogo: logoUrl ?? deposit.depositTargetLogo,\n logo: logoUrl ?? deposit.logo,\n protocol: appName ?? deposit.protocol,\n title: appName ?? deposit.title,\n };\n};\n\nconst getConfiguredDestinationPairs = (\n destination?: NexusWidgetDestination\n) => {\n const pairs: RuntimeNexusWidgetConfig[\"allowedDestinationPairs\"] = [];\n const chain = getConfiguredDestinationChainId(destination);\n if (!chain) return pairs;\n for (const token of destination?.tokens ?? []) {\n const address = getConfiguredDestinationTokenAddress(token);\n if (!address) continue;\n pairs.push({ chain, token: address });\n }\n return pairs;\n};\n\nconst hasConfiguredDestinationTokenList = (\n destination?: NexusWidgetDestination\n) => Boolean(destination?.tokens?.length);\n\nconst getConfiguredPrefillTokenPair = (\n prefill?: { token?: NexusWidgetPrefillToken }\n): RuntimeDestinationPair | undefined => {\n const token = prefill?.token;\n if (!token) return undefined;\n const chain = normalizeConfiguredChainId(token.chain);\n const address = getConfiguredDestinationTokenAddress(token);\n const symbol = getConfiguredDestinationTokenSymbol(token);\n if (!chain || !address || !symbol) return undefined;\n return {\n chain,\n decimals: token.decimals,\n logo: normalizeConfiguredString(token.logo),\n symbol,\n token: address,\n };\n};\n\nconst getConfiguredDestinationChainIds = (\n destination?: NexusWidgetDestination\n) => {\n const chain = getConfiguredDestinationChainId(destination);\n return chain ? [chain] : [];\n};\n\nconst toDepositConfigFromDestination = (\n config: NexusWidgetDepositConfig,\n token: NexusWidgetDestinationToken,\n appearance?: RuntimeNexusWidgetAppearance\n): NexusWidgetDepositOpportunityConfig | undefined => {\n const chainId = getConfiguredDestinationChainId(config.destination);\n const depositAddress = normalizeConfiguredAddress(config.depositAddress);\n const tokenAddress = getConfiguredDestinationTokenAddress(token);\n const tokenSymbol = getConfiguredDestinationTokenSymbol(token);\n if (\n !chainId ||\n !depositAddress ||\n !tokenAddress ||\n !tokenSymbol ||\n typeof config.executeDeposit !== \"function\"\n ) {\n return undefined;\n }\n\n const chainMeta = CHAIN_METADATA[chainId];\n return {\n chainId,\n depositTargetLogo: appearance?.logoUrl,\n executeDeposit: config.executeDeposit,\n logo: appearance?.logoUrl ?? token.logo ?? undefined,\n protocol:\n appearance?.appName ??\n appearance?.widgetHeading ??\n \"Deposit\",\n subtitle:\n chainMeta?.name\n ? `on ${getShortChainName(chainId, chainMeta.name)}`\n : undefined,\n title: appearance?.appName ?? appearance?.widgetHeading ?? \"Deposit\",\n tokenAddress,\n tokenDecimals: token.decimals ?? 18,\n tokenLogo: token.logo,\n tokenSymbol,\n };\n};\n\nconst getNexusWidgetDepositOptions = (\n config: NexusWidgetConfig,\n appearance?: RuntimeNexusWidgetAppearance\n) => {\n if (config.mode !== \"deposit\") return [];\n return (config.destination.tokens ?? [])\n .map((token) => toDepositConfigFromDestination(config, token, appearance))\n .filter((deposit): deposit is NexusWidgetDepositOpportunityConfig => Boolean(deposit));\n};\n\nconst normalizeNexusWidgetConfig = (\n rawConfig: NexusWidgetConfig\n): NormalizedNexusWidgetConfig => {\n const appearance = normalizeNexusWidgetAppearance(rawConfig.appearance);\n const amountInput = normalizeNexusWidgetAmountInput(rawConfig);\n const prefill: NexusWidgetRuntimePrefill = {};\n let activeMode: NexusWidgetMode =\n rawConfig.mode === \"deposit\" ||\n rawConfig.mode === \"send\" ||\n rawConfig.mode === \"swap\"\n ? rawConfig.mode\n : \"swap\";\n let isRecipientLocked = false;\n const depositOptions = getNexusWidgetDepositOptions(rawConfig, appearance).map(\n (deposit) => applyNexusWidgetAppearanceToDeposit(deposit, appearance)\n );\n let allowedDestinationPairs:\n | RuntimeNexusWidgetConfig[\"allowedDestinationPairs\"]\n | undefined;\n let allowedDestinationChains:\n | RuntimeNexusWidgetConfig[\"allowedDestinationChains\"]\n | undefined;\n\n if (amountInput?.value) {\n prefill.amount = amountInput.value;\n }\n\n if (rawConfig.mode === \"deposit\") {\n activeMode = \"deposit\";\n const pairs = getConfiguredDestinationPairs(rawConfig.destination);\n if (pairs.length > 0) {\n allowedDestinationPairs = pairs;\n prefill.destination = pairs[0];\n }\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (chainIds.length > 0) {\n allowedDestinationChains = chainIds;\n }\n } else if (rawConfig.mode === \"send\") {\n const recipient = normalizeConfiguredAddress(rawConfig.recipientAddress);\n if (recipient) {\n prefill.recipient = recipient;\n isRecipientLocked = true;\n }\n\n const hasDestinationTokens = hasConfiguredDestinationTokenList(\n rawConfig.destination\n );\n const pairs = getConfiguredDestinationPairs(rawConfig.destination);\n if (pairs.length > 0) {\n allowedDestinationPairs = pairs;\n prefill.destination ??= pairs[0];\n } else if (!hasDestinationTokens) {\n const prefillToken = getConfiguredPrefillTokenPair(rawConfig.prefill);\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (\n prefillToken &&\n (!chainIds.length || chainIds.includes(prefillToken.chain))\n ) {\n prefill.destination = prefillToken;\n }\n }\n\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (chainIds.length > 0) {\n allowedDestinationChains = chainIds;\n }\n } else if (rawConfig.mode === \"swap\") {\n const recipient = normalizeConfiguredAddress(rawConfig.recipientAddress);\n if (recipient) {\n prefill.recipient = recipient;\n }\n\n const hasDestinationTokens = hasConfiguredDestinationTokenList(\n rawConfig.destination\n );\n const pairs = getConfiguredDestinationPairs(rawConfig.destination);\n if (pairs.length > 0) {\n allowedDestinationPairs = pairs;\n prefill.destination ??= pairs[0];\n } else if (!hasDestinationTokens) {\n const prefillToken = getConfiguredPrefillTokenPair(rawConfig.prefill);\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (\n prefillToken &&\n (!chainIds.length || chainIds.includes(prefillToken.chain))\n ) {\n prefill.destination = prefillToken;\n }\n }\n\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (chainIds.length > 0) {\n allowedDestinationChains = chainIds;\n }\n }\n\n const runtimeConfig: RuntimeNexusWidgetConfig = {\n allowedDestinationChains,\n allowedDestinationPairs,\n deposit:\n activeMode === \"deposit\"\n ? depositOptions[0]\n : undefined,\n deposits: activeMode === \"deposit\" ? depositOptions : [],\n appearance,\n mode: activeMode,\n prefill,\n };\n\n return {\n activeMode,\n amountInput,\n appearance,\n config: runtimeConfig,\n depositOptions,\n isAmountFixed: false,\n isRecipientLocked,\n };\n};\n\nconst getDepositForTokenSelection = (\n deposits: NexusWidgetDepositOpportunityConfig[],\n token?: SwapTokenOption | null\n) => {\n if (!token) return undefined;\n return deposits.find(\n (deposit) =>\n deposit.chainId === token.chainId &&\n deposit.tokenAddress.toLowerCase() ===\n token.contractAddress.toLowerCase()\n );\n};\n\nconst sanitizeOpportunityForHistory = (\n opportunity?: NexusWidgetDepositOpportunityMetadata\n): NexusWidgetDepositOpportunityMetadata | undefined => {\n if (!opportunity) return undefined;\n return {\n label: opportunity.label,\n protocol: opportunity.protocol,\n logo: opportunity.logo,\n title: opportunity.title,\n subtitle: opportunity.subtitle,\n chainId: opportunity.chainId,\n tokenSymbol: opportunity.tokenSymbol,\n tokenDecimals: opportunity.tokenDecimals,\n tokenLogo: opportunity.tokenLogo,\n tokenAddress: opportunity.tokenAddress,\n apy: opportunity.apy,\n description: opportunity.description,\n };\n};\n\nconst sanitizeHistoryEntry = (entry: SwapHistoryEntry): SwapHistoryEntry => ({\n ...entry,\n createdAt: entry.createdAt ?? entry.startedAt ?? Date.now(),\n failureMessage:\n entry.status === \"timeout\" ? TIMEOUT_LABEL : entry.failureMessage,\n opportunity: sanitizeOpportunityForHistory(entry.opportunity),\n});\n\nconst sortSwapHistoryEntries = (entries: SwapHistoryEntry[]) =>\n [...entries].sort(\n (a, b) =>\n (b.createdAt ?? b.startedAt ?? 0) - (a.createdAt ?? a.startedAt ?? 0)\n );\n\nconst isStoredHistoryStatus = (value: unknown): value is SwapHistoryStatus =>\n value === \"pending\" ||\n value === \"fulfilled\" ||\n value === \"failed\" ||\n value === \"timeout\" ||\n value === \"refund-initiated\";\n\nconst isStoredMode = (value: unknown): value is NexusWidgetMode =>\n value === \"swap\" || value === \"deposit\" || value === \"send\";\n\nconst normalizeStoredHistoryEntry = (\n value: unknown\n): SwapHistoryEntry | null => {\n if (!value || typeof value !== \"object\") return null;\n const entry = value as Partial;\n const startedAt =\n typeof entry.startedAt === \"number\" && Number.isFinite(entry.startedAt)\n ? entry.startedAt\n : undefined;\n const createdAt =\n typeof entry.createdAt === \"number\" && Number.isFinite(entry.createdAt)\n ? entry.createdAt\n : startedAt;\n\n if (\n !entry.id ||\n typeof entry.id !== \"string\" ||\n !isStoredMode(entry.mode) ||\n !isStoredHistoryStatus(entry.status) ||\n !createdAt ||\n !startedAt\n ) {\n return null;\n }\n\n return {\n ...entry,\n id: entry.id,\n mode: entry.mode,\n status: entry.status,\n createdAt,\n startedAt,\n failureMessage:\n entry.status === \"timeout\" ? TIMEOUT_LABEL : entry.failureMessage,\n intentData: entry.intentData ?? null,\n fromTokens: Array.isArray(entry.fromTokens) ? entry.fromTokens : [],\n opportunity: sanitizeOpportunityForHistory(entry.opportunity),\n } as SwapHistoryEntry;\n};\n\nconst readSwapHistoryFromStorage = (storageKey: string): SwapHistoryEntry[] => {\n if (typeof window === \"undefined\") return [];\n\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (!raw) return [];\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n return sortSwapHistoryEntries(\n parsed\n .map(normalizeStoredHistoryEntry)\n .filter((entry): entry is SwapHistoryEntry => Boolean(entry))\n );\n } catch {\n return [];\n }\n};\n\nconst writeSwapHistoryToStorage = (\n storageKey: string,\n entries: SwapHistoryEntry[]\n) => {\n if (typeof window === \"undefined\") return;\n\n try {\n const persistableEntries =\n sortSwapHistoryEntries(entries).map(sanitizeHistoryEntry);\n window.localStorage.setItem(\n storageKey,\n JSON.stringify(persistableEntries, (_key, value) =>\n typeof value === \"bigint\" ? value.toString() : value\n )\n );\n } catch {\n // localStorage can be unavailable or full; in-memory history still works.\n }\n};\n\nfunction QuoteRefreshCountdown({\n progress,\n isRefreshing,\n secondsRemaining,\n}: {\n progress: number;\n isRefreshing: boolean;\n secondsRemaining: number;\n}) {\n const [showTooltip, setShowTooltip] = useState(false);\n const radius = 7;\n const circumference = 2 * Math.PI * radius;\n const clampedProgress = Math.max(0, Math.min(1, progress));\n const tooltipLabel = isRefreshing\n ? \"Refreshing quotes...\"\n : `Refreshing quotes in ${Math.max(0, secondsRemaining)} second${\n secondsRemaining === 1 ? \"\" : \"s\"\n }`;\n\n return (\n setShowTooltip(false)}\n onFocus={() => setShowTooltip(true)}\n onMouseEnter={() => setShowTooltip(true)}\n onMouseLeave={() => setShowTooltip(false)}\n style={{\n alignItems: \"center\",\n backgroundColor: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n height: \"22px\",\n justifyContent: \"center\",\n outline: \"1px solid var(--nexus-widget-border, #E8E8E7)\",\n position: \"relative\",\n width: \"22px\",\n }}\n tabIndex={0}\n >\n {showTooltip && (\n \n {tooltipLabel}\n \n )}\n \n \n \n \n \n );\n}\n\nconst toViemDecimalString = (value: unknown, decimals: number) => {\n const parsed = parseDecimalLoose(value);\n if (!parsed || parsed.lte(0)) return \"0\";\n return parsed\n .toDecimalPlaces(Math.max(0, decimals), Decimal.ROUND_DOWN)\n .toFixed();\n};\n\nconst formatDecimalDisplay = (\n value: unknown,\n options: { min?: number; max?: number } = {}\n) => {\n const amount = parseDecimalLoose(value) ?? new Decimal(0);\n const max = options.max ?? 2;\n return amount.toDecimalPlaces(max).toFixed();\n};\n\nconst formatUsdDisplay = (value: unknown) => {\n const amount = parseDecimalLoose(value) ?? new Decimal(0);\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n return `$${formatDecimalDisplay(amount, { min: 2, max: 2 })}`;\n};\n\nconst formatTokenDisplay = (value: unknown) => {\n const amount = parseDecimalLoose(value) ?? new Decimal(0);\n return formatDecimalDisplay(amount, { max: 8 });\n};\n\nconst getSwapTokenUsdValue = (token: SwapTokenOption) =>\n parseDecimalLoose(token.userAmountUsd) ??\n parseDecimalLoose(token.balanceInFiat) ??\n new Decimal(0);\n\nconst getSwapTokenBalanceUsdValue = (token: SwapTokenOption) =>\n parseDecimalLoose(token.balanceInFiat) ?? new Decimal(0);\n\nconst sortSwapTokensByUsdDesc = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const usdDelta = getSwapTokenUsdValue(b).cmp(getSwapTokenUsdValue(a));\n if (usdDelta !== 0) return usdDelta;\n return (a.symbol ?? \"\").localeCompare(b.symbol ?? \"\");\n });\n\nconst sortDisplaySourcesByBalanceUsdDesc = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const balanceUsdDelta = getSwapTokenBalanceUsdValue(b).cmp(\n getSwapTokenBalanceUsdValue(a)\n );\n if (balanceUsdDelta !== 0) return balanceUsdDelta;\n\n const spendUsdDelta = getSwapTokenUsdValue(b).cmp(getSwapTokenUsdValue(a));\n if (spendUsdDelta !== 0) return spendUsdDelta;\n\n return `${a.symbol ?? \"\"} ${a.chainName ?? \"\"}`.localeCompare(\n `${b.symbol ?? \"\"} ${b.chainName ?? \"\"}`\n );\n });\n\nconst getIntentSourceUsdValue = (source: SwapIntentData[\"sources\"][number]) =>\n parseDecimalLoose(source.value) ?? new Decimal(0);\n\nconst sortIntentSourcesByUsdDesc = (sources: SwapIntentData[\"sources\"]) =>\n [...sources].sort((a, b) => {\n const usdDelta = getIntentSourceUsdValue(b).cmp(getIntentSourceUsdValue(a));\n if (usdDelta !== 0) return usdDelta;\n return (a.token?.symbol ?? \"\").localeCompare(b.token?.symbol ?? \"\");\n });\n\nconst extractIntentIdFromUrl = (url?: string | null) => {\n if (!url) return undefined;\n const match = url.match(/(\\d+)(?:\\/)?$/);\n if (!match) return undefined;\n const parsed = Number(match[1]);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n};\n\nconst getNonEmptyString = (...values: unknown[]) => {\n for (const value of values) {\n if (typeof value !== \"string\") continue;\n const trimmed = value.trim();\n if (trimmed.length > 0) return trimmed;\n }\n return null;\n};\n\nconst isHttpUrl = (value?: string | null): value is string =>\n Boolean(value && /^https?:\\/\\//i.test(value));\n\nconst hasValidIntentExplorer = (\n entry: Pick\n) => isHttpUrl(entry.intentExplorerUrl);\n\nconst getHistoryExplorerUrl = (\n entry: Pick<\n SwapHistoryEntry,\n \"finalExplorerUrl\" | \"intentExplorerUrl\" | \"sourceExplorerUrl\"\n >\n) =>\n [\n entry.intentExplorerUrl,\n entry.finalExplorerUrl,\n entry.sourceExplorerUrl,\n ].find(isHttpUrl) ?? null;\n\nconst getFiniteNumber = (...values: unknown[]) => {\n for (const value of values) {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"string\") continue;\n const parsed = Number(value);\n if (Number.isFinite(parsed)) return parsed;\n }\n return undefined;\n};\n\nconst getObjectChainId = (value: any) =>\n getFiniteNumber(\n value?.chainId,\n value?.chain?.id,\n value?.chain?.chainId,\n value?.toChainId,\n value?.destinationChainId,\n value?.data?.chainId,\n value?.data?.chain?.id,\n value?.data?.chain?.chainId,\n value?.data?.toChainId,\n value?.data?.destinationChainId,\n value?.result?.chainId,\n value?.result?.chain?.id\n );\n\nconst getExplorerBaseUrl = (chainId?: number, ...candidates: unknown[]) => {\n const directCandidates = candidates.flatMap((candidate: any) => [\n candidate?.blockExplorerUrl,\n candidate?.blockExplorerURL,\n candidate?.chainBlockExplorerUrl,\n candidate?.explorerBaseUrl,\n candidate?.explorerUrlBase,\n candidate?.blockExplorerUrls?.[0],\n candidate?.blockExplorers?.default?.url,\n candidate?.chain?.blockExplorerUrl,\n candidate?.chain?.blockExplorerURL,\n candidate?.chain?.chainBlockExplorerUrl,\n candidate?.chain?.explorerBaseUrl,\n candidate?.chain?.explorerUrlBase,\n candidate?.chain?.blockExplorerUrls?.[0],\n candidate?.chain?.blockExplorers?.default?.url,\n candidate?.data?.blockExplorerUrl,\n candidate?.data?.blockExplorerURL,\n candidate?.data?.chainBlockExplorerUrl,\n candidate?.data?.blockExplorerUrls?.[0],\n candidate?.data?.blockExplorers?.default?.url,\n candidate?.data?.chain?.blockExplorerUrl,\n candidate?.data?.chain?.blockExplorerURL,\n candidate?.data?.chain?.chainBlockExplorerUrl,\n candidate?.data?.chain?.blockExplorerUrls?.[0],\n candidate?.data?.chain?.blockExplorers?.default?.url,\n ]);\n return getNonEmptyString(\n ...directCandidates,\n chainId ? CHAIN_METADATA[chainId]?.blockExplorerUrls?.[0] : undefined,\n chainId\n ? (CHAIN_METADATA[chainId] as any)?.blockExplorers?.default?.url\n : undefined\n );\n};\n\nconst getTransactionHash = (...values: unknown[]) => {\n for (const value of values) {\n if (typeof value !== \"string\") continue;\n const trimmed = value.trim();\n if (/^0x[a-fA-F0-9]{64}$/.test(trimmed)) return trimmed;\n }\n return null;\n};\n\nconst getIntentHash = (...values: unknown[]) => getTransactionHash(...values);\n\nconst getObjectIntentHash = (value: any) =>\n getIntentHash(\n value?.intentHash,\n value?.intent_hash,\n value?.intent?.hash,\n value?.intent?.intentHash,\n value?.intent?.intent_hash,\n value?.requestHash,\n value?.request_hash,\n value?.request?.hash,\n value?.request?.requestHash,\n value?.rffHash,\n value?.rff_hash,\n value?.rff?.hash,\n value?.data?.intentHash,\n value?.data?.intent_hash,\n value?.data?.intent?.hash,\n value?.data?.intent?.intentHash,\n value?.data?.intent?.intent_hash,\n value?.data?.requestHash,\n value?.data?.request_hash,\n value?.data?.request?.hash,\n value?.data?.request?.requestHash,\n value?.data?.rffHash,\n value?.data?.rff_hash,\n value?.data?.rff?.hash,\n value?.result?.intentHash,\n value?.result?.intent_hash,\n value?.result?.intent?.hash,\n value?.result?.requestHash,\n value?.result?.request_hash,\n value?.result?.rffHash,\n value?.result?.rff_hash\n );\n\nconst getNexusExplorerNetwork = (network?: unknown) => {\n const normalized =\n typeof network === \"string\" ? network.trim().toLowerCase() : \"\";\n if (normalized === \"canary\" || normalized === \"testnet\") return normalized;\n return \"mainnet\";\n};\n\nconst getRffExplorerUrl = (network: unknown, intentHash?: string | null) =>\n intentHash\n ? `https://nexus-v2.${getNexusExplorerNetwork(network)}.avail.so/rff/${intentHash}`\n : null;\n\nconst getObjectTransactionHash = (value: any) =>\n getTransactionHash(\n value?.txHash,\n value?.transactionHash,\n value?.executeTxHash,\n value?.executeTransactionHash,\n value?.transferTransactionHash,\n value?.receipt?.transactionHash,\n value?.tx?.hash,\n value?.transaction?.hash,\n value?.data?.txHash,\n value?.data?.transactionHash,\n value?.data?.executeTxHash,\n value?.data?.executeTransactionHash,\n value?.data?.transferTransactionHash,\n value?.data?.receipt?.transactionHash,\n value?.data?.tx?.hash,\n value?.data?.transaction?.hash,\n value?.result?.txHash,\n value?.result?.transactionHash,\n value?.result?.receipt?.transactionHash\n );\n\nconst getExplorerTxUrl = (\n chainId?: number,\n txHash?: string | null,\n ...candidates: unknown[]\n) => {\n if (!chainId || !txHash) return null;\n const baseUrl = getExplorerBaseUrl(chainId, ...candidates);\n return baseUrl ? `${String(baseUrl).replace(/\\/$/, \"\")}/tx/${txHash}` : null;\n};\n\nconst getSdkSwapResult = (result: any) => {\n const candidate = result?.swapResult ?? result?.result;\n return candidate && typeof candidate === \"object\" ? candidate : null;\n};\n\nconst getSdkTransactionHash = (result: any) =>\n getObjectTransactionHash(result) ||\n getObjectTransactionHash(result?.executeResponse) ||\n getObjectTransactionHash(result?.execute) ||\n getObjectTransactionHash(result?.transfer) ||\n getObjectTransactionHash(result?.swapResult) ||\n getObjectTransactionHash(result?.result) ||\n null;\n\nconst getSdkExplorerUrl = (result: any) =>\n getNonEmptyString(\n result?.explorerUrl,\n result?.explorerURL,\n result?.txExplorerUrl,\n result?.transactionExplorerUrl,\n result?.execute?.explorerUrl,\n result?.execute?.explorerURL,\n result?.execute?.txExplorerUrl,\n result?.execute?.transactionExplorerUrl,\n result?.executeResponse?.explorerUrl,\n result?.executeResponse?.explorerURL,\n result?.executeResponse?.txExplorerUrl,\n result?.executeResponse?.transactionExplorerUrl,\n result?.executeExplorerUrl,\n result?.transferExplorerUrl,\n result?.swapResult?.explorerUrl,\n result?.swapResult?.explorerURL,\n result?.swapResult?.txExplorerUrl,\n result?.swapResult?.transactionExplorerUrl,\n result?.result?.explorerUrl,\n result?.result?.explorerURL,\n result?.result?.txExplorerUrl,\n result?.result?.transactionExplorerUrl\n );\n\nconst getSdkIntentExplorerUrl = (result: any, swapResult?: any) =>\n getNonEmptyString(\n swapResult?.intentExplorerUrl,\n swapResult?.intentExplorerURL,\n swapResult?.intentUrl,\n swapResult?.intentURL,\n swapResult?.rffUrl,\n swapResult?.rffURL,\n swapResult?.rffExplorerUrl,\n swapResult?.rffExplorerURL,\n swapResult?.explorerUrl,\n swapResult?.explorerURL,\n result?.intentExplorerUrl,\n result?.intentExplorerURL,\n result?.intentUrl,\n result?.intentURL,\n result?.rffUrl,\n result?.rffURL,\n result?.rffExplorerUrl,\n result?.rffExplorerURL,\n result?.swapResult?.intentExplorerUrl,\n result?.swapResult?.intentExplorerURL,\n result?.swapResult?.intentUrl,\n result?.swapResult?.intentURL,\n result?.swapResult?.rffUrl,\n result?.swapResult?.rffURL,\n result?.swapResult?.rffExplorerUrl,\n result?.swapResult?.rffExplorerURL,\n result?.swapResult?.explorerUrl,\n result?.swapResult?.explorerURL,\n result?.result?.intentExplorerUrl,\n result?.result?.intentExplorerURL,\n result?.result?.intentUrl,\n result?.result?.intentURL,\n result?.result?.rffUrl,\n result?.result?.rffURL,\n result?.result?.rffExplorerUrl,\n result?.result?.rffExplorerURL,\n result?.result?.explorerUrl,\n result?.result?.explorerURL\n );\n\nconst getSdkIntentExplorerUrlForNetwork = (\n network: unknown,\n result: any,\n swapResult?: any\n) =>\n getSdkIntentExplorerUrl(result, swapResult) ||\n getRffExplorerUrl(\n network,\n getObjectIntentHash(swapResult) || getObjectIntentHash(result)\n );\n\nfunction MiniLogo({\n src,\n label,\n size = 30,\n fontSize = 13,\n outline,\n style,\n}: {\n src?: string;\n label?: string;\n size?: number;\n fontSize?: number;\n outline?: string;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n background: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n outline,\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").trim().slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction TokenLogoPair({\n tokenLogo,\n chainLogo,\n tokenSymbol,\n chainName,\n tokenOutline,\n size = 34,\n}: {\n tokenLogo?: string;\n chainLogo?: string;\n tokenSymbol?: string;\n chainName?: string;\n tokenOutline?: string;\n size?: number;\n}) {\n return (\n \n \n {chainLogo && (\n \n )}\n \n );\n}\n\nfunction SourceLogoStack({\n sources,\n size = 24,\n maxVisible = 3,\n}: {\n sources: HistorySourceRow[];\n size?: number;\n maxVisible?: number;\n}) {\n const visibleSources = sources.slice(0, maxVisible);\n const hiddenCount = Math.max(0, sources.length - visibleSources.length);\n\n return (\n \n {visibleSources.map((source, index) => (\n \n \n \n ))}\n {hiddenCount > 0 && (\n \n +{hiddenCount}\n \n )}\n \n );\n}\n\nfunction TruncatedAddress({\n address,\n color = \"var(--foreground-brand)\",\n}: {\n address: string;\n color?: string;\n}) {\n const [showTooltip, setShowTooltip] = useState(false);\n const label =\n address.length > 12\n ? `${address.slice(0, 6)}...${address.slice(-4)}`\n : address;\n\n return (\n setShowTooltip(false)}\n onFocus={() => setShowTooltip(true)}\n onMouseEnter={() => setShowTooltip(true)}\n onMouseLeave={() => setShowTooltip(false)}\n style={{\n color,\n display: \"inline-flex\",\n fontFamily: uiFont,\n fontSize: \"15px\",\n fontWeight: 500,\n lineHeight: \"20px\",\n outline: \"none\",\n position: \"relative\",\n }}\n tabIndex={0}\n >\n {label}\n {showTooltip && (\n \n {address}\n \n )}\n \n );\n}\n\nconst getDisplayDestinationSourceRow = (\n entry: SwapHistoryEntry\n): HistorySourceRow | null => {\n if (entry.mode !== \"deposit\" && entry.mode !== \"send\") return null;\n if (!entry.toToken || !entry.requestedToAmount) return null;\n\n const requestedAmount = parseDecimalLoose(entry.requestedToAmount);\n const intentDestinationAmount = parseDecimalLoose(\n entry.intentData?.destination.amount\n );\n const destinationBalanceAmount = parseDecimalLoose(\n entry.toToken.balance\n );\n if (\n !requestedAmount ||\n !destinationBalanceAmount ||\n requestedAmount.lte(0) ||\n destinationBalanceAmount.lte(0)\n ) {\n return null;\n }\n\n const intentCoversAmount = intentDestinationAmount ?? new Decimal(0);\n const displayAmount = Decimal.min(\n destinationBalanceAmount,\n Decimal.max(0, requestedAmount.minus(intentCoversAmount))\n );\n if (displayAmount.lte(0)) return null;\n\n const requestedValue = parseDecimalLoose(entry.requestedToValue);\n const destinationValue = parseDecimalLoose(\n entry.intentData?.destination.value\n );\n const rate =\n requestedValue && requestedAmount.gt(0)\n ? requestedValue.div(requestedAmount)\n : destinationValue && intentCoversAmount.gt(0)\n ? destinationValue.div(intentCoversAmount)\n : undefined;\n\n return {\n key: `destination-balance-${entry.toToken.chainId}-${entry.toToken.contractAddress}`,\n chainId: entry.toToken.chainId,\n contractAddress: entry.toToken.contractAddress,\n tokenLogo: entry.intentData?.destination.token.logo || entry.toToken.logo,\n chainLogo: entry.toToken.chainLogo,\n symbol: entry.toToken.symbol,\n chainName: getShortChainName(\n entry.toToken.chainId,\n entry.toToken.chainName\n ),\n amount: displayAmount\n .toDecimalPlaces(\n Math.max(0, entry.toToken.decimals ?? 18),\n Decimal.ROUND_DOWN\n )\n .toFixed(),\n value: rate\n ? displayAmount.mul(rate).toFixed()\n : entry.toToken.balanceInFiat,\n };\n};\n\nconst getHistorySourceRowMergeKey = (row: HistorySourceRow) => {\n const chainKey = row.chainId ?? row.chainName;\n const address = row.contractAddress?.toLowerCase();\n return address\n ? `${chainKey}:${address}`\n : `${chainKey}:symbol:${row.symbol.toUpperCase()}`;\n};\n\nconst mergeHistorySourceRows = (rows: HistorySourceRow[]) => {\n const merged = new Map();\n\n for (const row of rows) {\n const key = getHistorySourceRowMergeKey(row);\n const existing = merged.get(key);\n if (!existing) {\n merged.set(key, row);\n continue;\n }\n\n merged.set(key, {\n ...existing,\n amount: sumDecimalStrings(existing.amount, row.amount) ?? existing.amount,\n chainLogo: existing.chainLogo || row.chainLogo,\n key: existing.key,\n tokenLogo: existing.tokenLogo || row.tokenLogo,\n value: sumDecimalStrings(\n String(existing.value ?? \"\"),\n String(row.value ?? \"\")\n ),\n });\n }\n\n return Array.from(merged.values());\n};\n\nconst getProgressStepType = (step?: SwapStepType | BridgeStepType | null) =>\n String((step as any)?.type ?? (step as any)?.typeID ?? \"\").toUpperCase();\n\nconst isSourceMovementProgressStep = (type: string, rawStepType: string) =>\n rawStepType === \"source_swap\" ||\n rawStepType === \"eoa_to_ephemeral_transfer\" ||\n rawStepType === \"bridge_deposit\" ||\n rawStepType === \"vault_deposit\" ||\n type.includes(\"SOURCE_SWAP\") ||\n type.includes(\"EOA_TO_EPHEMERAL_TRANSFER\") ||\n type.includes(\"BRIDGE_DEPOSIT\") ||\n type.includes(\"VAULT_DEPOSIT\");\n\nconst isBridgeRefundStepType = (type: string) =>\n type.includes(\"BRIDGE_INTENT_SUBMISSION\") || type.includes(\"BRIDGE_DEPOSIT\");\n\nconst isSwapSkippedStepType = (type: string) => type.includes(\"SWAP_SKIPPED\");\n\nconst isAutoRefundAvailableProgressEvent = (event?: NexusWidgetProgressEvent) =>\n event?.name === PROGRESS_EVENT_NAMES.SWAP_PLAN_PROGRESS &&\n isBridgeRefundStepType(getProgressStepType(event.step));\n\nconst normalizeBridgeProvider = (\n value: unknown\n): BridgeProvider | undefined => {\n if (value === \"nexus\" || value === \"mayan\" || value === null) {\n return value;\n }\n return undefined;\n};\n\nconst normalizePlanStepType = (stepType: unknown, state?: unknown) => {\n const normalized = String(stepType ?? \"\").toLowerCase();\n const normalizedState = String(state ?? \"\").toLowerCase();\n\n if (normalized === \"execute_transaction\") {\n return normalizedState === \"confirmed\" || normalizedState === \"completed\"\n ? \"TRANSACTION_CONFIRMED\"\n : \"TRANSACTION_SENT\";\n }\n\n const mapped: Record = {\n allowance: \"ALLOWANCE\",\n allowance_approval: \"ALLOWANCE_APPROVAL\",\n bridge_deposit: \"BRIDGE_DEPOSIT\",\n bridge_fill: \"BRIDGE_FILL\",\n bridge_intent_submission: \"BRIDGE_INTENT_SUBMISSION\",\n destination_swap: \"DESTINATION_SWAP\",\n eoa_to_ephemeral_transfer: \"EOA_TO_EPHEMERAL_TRANSFER\",\n execute_approval: \"APPROVAL\",\n request_signing: \"REQUEST_SIGNING\",\n request_submission: \"REQUEST_SUBMISSION\",\n source_swap: \"SOURCE_SWAP\",\n vault_deposit: \"BRIDGE_DEPOSIT\",\n };\n\n return mapped[normalized] ?? normalized.toUpperCase();\n};\n\nconst normalizePlanStep = (\n stepLike: unknown,\n fallbackStepType?: unknown,\n state?: unknown,\n completed?: boolean\n): SwapStepType | BridgeStepType => {\n const source =\n stepLike && typeof stepLike === \"object\" ? (stepLike as any) : {};\n const rawStepType = fallbackStepType ?? source.stepType ?? source.type;\n const progressType = normalizePlanStepType(\n rawStepType ?? source.typeID,\n state\n );\n const progressKey =\n source.id ?? source.stepId ?? source.typeID ?? progressType;\n\n return {\n ...source,\n completed,\n rawType: rawStepType,\n type: progressType,\n typeID: String(progressKey),\n } as SwapStepType | BridgeStepType;\n};\n\nconst getPlanStepChainId = (event: any, step: any) =>\n getObjectChainId(event) ?? getObjectChainId(step);\n\nconst getPlanStepTransactionHash = (event: any, step: any) =>\n getObjectTransactionHash(event) ?? getObjectTransactionHash(step);\n\nconst getPlanStepExplorerUrl = (event: any, step: any) => {\n const directExplorerUrl = getNonEmptyString(\n event?.explorerUrl,\n event?.explorerURL,\n event?.txExplorerUrl,\n event?.transactionExplorerUrl,\n step?.explorerUrl,\n step?.explorerURL,\n step?.txExplorerUrl,\n step?.transactionExplorerUrl,\n step?.data?.explorerUrl,\n step?.data?.explorerURL,\n step?.data?.txExplorerUrl,\n step?.data?.transactionExplorerUrl\n );\n if (directExplorerUrl) return directExplorerUrl;\n\n return getExplorerTxUrl(\n getPlanStepChainId(event, step),\n getPlanStepTransactionHash(event, step),\n event,\n step\n );\n};\n\nconst getPlanStepIntentExplorerUrl = (event: any, step: any) =>\n getNonEmptyString(\n event?.intentExplorerUrl,\n event?.intentExplorerURL,\n event?.intentUrl,\n event?.intentURL,\n event?.rffUrl,\n event?.rffURL,\n event?.rffExplorerUrl,\n event?.rffExplorerURL,\n step?.intentExplorerUrl,\n step?.intentExplorerURL,\n step?.intentUrl,\n step?.intentURL,\n step?.rffUrl,\n step?.rffURL,\n step?.rffExplorerUrl,\n step?.rffExplorerURL,\n step?.data?.intentExplorerUrl,\n step?.data?.intentExplorerURL,\n step?.data?.intentUrl,\n step?.data?.intentURL,\n step?.data?.rffUrl,\n step?.data?.rffURL,\n step?.data?.rffExplorerUrl,\n step?.data?.rffExplorerURL\n );\n\nconst isIntentSubmissionLikeEvent = (event: any, step?: any) => {\n const text = [\n event?.type,\n event?.event,\n event?.name,\n event?.status,\n event?.stepType,\n step?.type,\n step?.typeID,\n step?.rawType,\n ]\n .filter((value) => value !== null && value !== undefined)\n .join(\" \")\n .toLowerCase();\n\n return (\n text.includes(\"intent\") ||\n text.includes(\"request_submission\") ||\n text.includes(\"rff\")\n );\n};\n\nconst getGenericEventHash = (event: any, step?: any) =>\n getTransactionHash(\n event?.hash,\n event?.data?.hash,\n event?.result?.hash,\n step?.hash,\n step?.data?.hash,\n step?.result?.hash\n );\n\nconst getEventIntentExplorerUrl = (\n network: unknown,\n event: any,\n step?: any\n) => {\n const directUrl = step\n ? getPlanStepIntentExplorerUrl(event, step)\n : getNonEmptyString(\n event?.intentExplorerUrl,\n event?.intentExplorerURL,\n event?.intentUrl,\n event?.intentURL,\n event?.rffUrl,\n event?.rffURL,\n event?.rffExplorerUrl,\n event?.rffExplorerURL,\n event?.data?.intentExplorerUrl,\n event?.data?.intentExplorerURL,\n event?.data?.intentUrl,\n event?.data?.intentURL,\n event?.data?.rffUrl,\n event?.data?.rffURL,\n event?.data?.rffExplorerUrl,\n event?.data?.rffExplorerURL\n );\n if (directUrl) return directUrl;\n\n return getRffExplorerUrl(\n network,\n getObjectIntentHash(event) ||\n getObjectIntentHash(step) ||\n (isIntentSubmissionLikeEvent(event, step)\n ? getGenericEventHash(event, step)\n : null)\n );\n};\n\nconst isTimeoutLikeError = (error: unknown) => {\n const err = error as {\n code?: unknown;\n name?: unknown;\n message?: unknown;\n shortMessage?: unknown;\n };\n const text = [\n err?.code,\n err?.name,\n err?.message,\n err?.shortMessage,\n typeof error === \"string\" ? error : undefined,\n ]\n .filter((value) => value !== null && value !== undefined)\n .join(\" \");\n\n return /timeout|timed out|time out|deadline exceeded|expired while waiting|wait.*expired|poll.*expired/i.test(\n text\n );\n};\n\nconst getSdkEventType = (event: any) =>\n event?.type ?? event?.name ?? event?.event ?? \"unknown\";\n\nconst summarizeSdkProgressStep = (\n step: SwapStepType | BridgeStepType | null | undefined,\n index?: number\n) => ({\n completed: (step as any)?.completed,\n index,\n rawType: (step as any)?.rawType ?? (step as any)?.stepType,\n state: (step as any)?.state,\n type: getProgressStepType(step),\n});\n\nconst logSdkSwapEvent = (\n label: string,\n event: any,\n meta?: Record\n) => {\n console.log(`[NexusWidget SDK][swap] ${label}`, {\n event,\n eventType: getSdkEventType(event),\n ...meta,\n });\n};\n\nconst logSdkIntentEvent = (\n label: string,\n data: any,\n meta?: Record\n) => {\n console.log(`[NexusWidget SDK][intent] ${label}`, {\n hasAllow: typeof data?.allow === \"function\",\n hasDeny: typeof data?.deny === \"function\",\n hasRefresh: typeof data?.refresh === \"function\",\n intent: data?.intent,\n raw: data,\n ...meta,\n });\n};\n\nconst logSdkIntentInput = (\n operation: string,\n input: unknown,\n meta?: Record\n) => {\n console.log(`[NexusWidget SDK][intent input] ${operation}`, {\n input,\n ...meta,\n });\n};\n\nconst normalizeSdkIntentString = (value: unknown) => {\n if (value === null || value === undefined || value === \"\") return undefined;\n return String(value);\n};\n\nconst normalizeSdkIntentAmount = (\n value: unknown,\n fallback: string = \"0\"\n) => normalizeSdkIntentString(value) ?? fallback;\n\nconst getLogoFromMetadata = (metadata: any) =>\n metadata?.logo ??\n metadata?.logoURI ??\n metadata?.logoUri ??\n metadata?.logoUrl ??\n metadata?.icon ??\n \"\";\n\nconst normalizeSdkIntentChain = (chain: any) => {\n const id = Number(chain?.id ?? chain?.chainId);\n if (!Number.isFinite(id)) return undefined;\n const chainMeta = CHAIN_METADATA[id];\n return {\n id,\n logo: getLogoFromMetadata(chain) || chainMeta?.logo || \"\",\n name: chain?.name ?? chainMeta?.name ?? \"\",\n };\n};\n\nconst normalizeSdkIntentToken = (token: any, chainId?: number) => {\n const chainMeta = chainId ? CHAIN_METADATA[chainId] : undefined;\n const decimals = Number(token?.decimals ?? chainMeta?.nativeCurrency.decimals);\n return {\n contractAddress:\n token?.contractAddress ??\n token?.address ??\n token?.tokenAddress ??\n zeroAddress,\n decimals: Number.isFinite(decimals) ? decimals : 18,\n logo: getLogoFromMetadata(token) || undefined,\n symbol: token?.symbol ?? token?.tokenSymbol ?? \"\",\n };\n};\n\nconst normalizeSdkIntentGas = (\n gas: any,\n chainId?: number\n): SwapIntentDestination[\"gas\"] => ({\n amount: normalizeSdkIntentAmount(gas?.amount),\n value: normalizeSdkIntentString(gas?.value),\n token: normalizeSdkIntentToken(gas?.token ?? gas, chainId),\n});\n\nconst normalizeSdkIntentSource = (\n source: any\n): SwapIntentSource | undefined => {\n const chain = normalizeSdkIntentChain(source?.chain);\n if (!chain) return undefined;\n return {\n ...source,\n amount: normalizeSdkIntentAmount(source?.amount),\n chain,\n token: normalizeSdkIntentToken(source?.token, chain.id),\n value: normalizeSdkIntentString(source?.value),\n };\n};\n\nconst normalizeSdkIntentDestination = (\n destination: any\n): SwapIntentDestination | undefined => {\n const chain = normalizeSdkIntentChain(destination?.chain);\n if (!chain) return undefined;\n return {\n ...destination,\n amount: normalizeSdkIntentAmount(destination?.amount),\n chain,\n gas: normalizeSdkIntentGas(destination?.gas, chain.id),\n token: normalizeSdkIntentToken(destination?.token, chain.id),\n value: normalizeSdkIntentString(destination?.value),\n };\n};\n\nconst normalizeSwapIntentData = (intent: any): SwapIntentData | null => {\n const destination = normalizeSdkIntentDestination(intent?.destination);\n if (!destination) return null;\n\n return {\n ...intent,\n destination,\n sources: Array.isArray(intent?.sources)\n ? intent.sources\n .map(normalizeSdkIntentSource)\n .filter(\n (source: SwapIntentSource | undefined): source is SwapIntentSource =>\n Boolean(source)\n )\n : [],\n };\n};\n\nconst normalizeSwapAndExecuteRequirementIntent = (\n intent: any\n): SwapIntentData | null => {\n const requirement = intent?.executeRequirement ?? intent?.executionRequirement;\n if (!requirement) return null;\n const destination = normalizeSdkIntentDestination({\n amount: requirement?.token?.amount,\n chain: requirement?.chain,\n gas: requirement?.gas,\n token: requirement?.token,\n value: requirement?.token?.value,\n });\n if (!destination) return null;\n\n return {\n ...intent,\n bridgeProvider: normalizeBridgeProvider(intent?.bridgeProvider),\n destination,\n feesAndBuffer: intent?.feesAndBuffer,\n sources: [],\n };\n};\n\nconst normalizeRenderableSwapIntentData = (\n rawIntent: any,\n bridgeProvider?: BridgeProvider\n): SwapIntentData | null => {\n const direct = normalizeSwapIntentData(rawIntent);\n const normalizedIntent = direct\n ? null\n : normalizeSwapIntentData(rawIntent?.normalizedIntent);\n const nestedSwap =\n direct || normalizedIntent ? null : normalizeSwapIntentData(rawIntent?.swap);\n const requirement = direct || normalizedIntent || nestedSwap\n ? null\n : normalizeSwapAndExecuteRequirementIntent(rawIntent);\n const normalized = direct ?? normalizedIntent ?? nestedSwap ?? requirement;\n if (!normalized) return null;\n\n return bridgeProvider === undefined\n ? normalized\n : { ...normalized, bridgeProvider };\n};\n\nconst logSwapPlanSteps = (\n eventType: \"plan_preview\" | \"plan_confirmed\",\n stepList: Array,\n rawSteps: unknown\n) => {\n console.log(`[NexusWidget SDK][swap] ${eventType} step list`, {\n count: stepList.length,\n eventType,\n rawSteps,\n steps: stepList.map((step, index) => summarizeSdkProgressStep(step, index)),\n });\n};\n\nconst logSwapPlanProgress = (\n event: any,\n step: SwapStepType | BridgeStepType,\n eventName: string,\n completed: boolean\n) => {\n console.log(\"[NexusWidget SDK][swap] plan_progress\", {\n completed,\n eventName,\n eventType: getSdkEventType(event),\n normalizedStep: summarizeSdkProgressStep(step),\n rawEvent: event,\n rawStep: event?.step,\n state: event?.state,\n stepType: event?.stepType,\n });\n};\n\nconst getFailureMessageForProgressStep = (\n step: SwapStepType | BridgeStepType | null | undefined,\n mode: NexusWidgetMode,\n autoRefundAvailable = false\n) => {\n if (autoRefundAvailable) {\n return \"Swap Failed. Refund Initiated\";\n }\n\n const type = getProgressStepType(step);\n if (\n type.includes(\"CREATE_PERMIT_FOR_SOURCE_SWAP\") ||\n type.includes(\"CREATE_PERMIT_EOA_TO_EPHEMERAL\") ||\n type.includes(\"EOA_EXECUTE_CALL\") ||\n type.includes(\"SOURCE_SWAP\") ||\n type.includes(\"COLLECTION\")\n ) {\n return \"Collection Failed\";\n }\n if (type.includes(\"DESTINATION_SWAP\") || type.includes(\"FULFIL\")) {\n return \"Destination Swap Failed\";\n }\n if (\n type.includes(\"TRANSACTION\") ||\n type.includes(\"APPROVAL\") ||\n type.includes(\"DEPOSIT\")\n ) {\n return mode === \"send\"\n ? \"Send failed. Funds are in your wallet\"\n : mode === \"deposit\"\n ? \"Deposit failed. Funds are in your wallet\"\n : \"Swap Failed\";\n }\n if (\n type.includes(\"SWAP\") ||\n type.includes(\"BRIDGE\") ||\n type.includes(\"INTENT\") ||\n type.includes(\"DETERMINING\")\n ) {\n return \"Swap Failed\";\n }\n return mode === \"send\"\n ? \"Send failed. Funds are in your wallet\"\n : mode === \"deposit\"\n ? \"Deposit failed. Funds are in your wallet\"\n : \"Swap Failed\";\n};\n\nconst getBridgeTokenSymbolForProgressStep = (\n step: SwapStepType | BridgeStepType | null | undefined\n) => {\n const rawStep = step as any;\n return (\n getNonEmptyString(\n rawStep?.bridgeToken?.symbol,\n rawStep?.data?.bridgeToken?.symbol,\n rawStep?.bridgeTokenSymbol,\n rawStep?.data?.bridgeTokenSymbol,\n rawStep?.swaps?.[0]?.input?.symbol,\n rawStep?.data?.swaps?.[0]?.input?.symbol,\n rawStep?.input?.symbol,\n rawStep?.data?.input?.symbol,\n rawStep?.asset?.symbol,\n rawStep?.data?.asset?.symbol\n ) ?? \"USDC\"\n );\n};\n\nconst getFailureDescriptionForProgressStep = (\n step: SwapStepType | BridgeStepType | null | undefined,\n autoRefundAvailable = false\n) => {\n if (autoRefundAvailable) return undefined;\n const type = getProgressStepType(step);\n if (!type.includes(\"DESTINATION_SWAP\")) return undefined;\n const bridgeTokenSymbol = getBridgeTokenSymbolForProgressStep(step);\n return `${bridgeTokenSymbol} has been bridged and you have those funds in your wallet.`;\n};\n\nconst getSourceRows = (entry: SwapHistoryEntry): HistorySourceRow[] => {\n const sources = entry.intentData?.sources ?? [];\n const displayDestinationSourceRow = getDisplayDestinationSourceRow(entry);\n if (sources.length > 0) {\n const sourceRows = sources.map((source, index) => {\n const fallback = entry.fromTokens.find(\n (token) =>\n token.chainId === source.chain.id &&\n (token.contractAddress?.toLowerCase() ===\n source.token.contractAddress?.toLowerCase() ||\n token.symbol === source.token.symbol)\n );\n\n return {\n key: `${source.chain.id}-${source.token.contractAddress}-${index}`,\n chainId: source.chain.id,\n contractAddress: source.token.contractAddress,\n tokenLogo: source.token.logo || fallback?.logo,\n chainLogo: source.chain.logo || fallback?.chainLogo,\n symbol: source.token.symbol,\n chainName: getShortChainName(source.chain.id, source.chain.name),\n amount: source.amount,\n value: source.value,\n };\n });\n\n return mergeHistorySourceRows(\n displayDestinationSourceRow\n ? [displayDestinationSourceRow, ...sourceRows]\n : sourceRows\n );\n }\n\n const fallbackRows = entry.fromTokens.map((token, index) => ({\n key: `${token.chainId}-${token.contractAddress}-${index}`,\n chainId: token.chainId,\n contractAddress: token.contractAddress,\n tokenLogo: token.logo,\n chainLogo: token.chainLogo,\n symbol: token.symbol,\n chainName: getShortChainName(token.chainId, token.chainName),\n amount: token.userAmount || \"0\",\n value: token.balanceInFiat,\n }));\n\n return mergeHistorySourceRows(\n displayDestinationSourceRow\n ? [displayDestinationSourceRow, ...fallbackRows]\n : fallbackRows\n );\n};\n\nfunction SourceRowsList({\n entry,\n maxHeight = 236,\n borderTopFirst = true,\n scrollAfterRows = 4,\n}: {\n entry: SwapHistoryEntry;\n maxHeight?: number;\n borderTopFirst?: boolean;\n scrollAfterRows?: number;\n}) {\n const rows = getSourceRows(entry);\n const shouldScroll = rows.length > scrollAfterRows;\n const scrollRef = useRef(null);\n\n return (\n
\n \n {rows.map((row, index) => (\n 0 ? \"1px solid var(--nexus-widget-border, #E8E8E7)\" : \"none\",\n display: \"flex\",\n justifyContent: \"space-between\",\n minHeight: \"64px\",\n padding: \"10px 20px\",\n }}\n >\n \n \n
\n \n {row.symbol}\n \n \n on {row.chainName || \"Unknown chain\"}\n \n
\n
\n \n \n {formatTokenDisplay(row.amount)} {row.symbol}\n \n \n {formatUsdDisplay(row.value)}\n \n \n \n ))}\n \n {shouldScroll && (\n \n scrollRef.current?.scrollBy({ top: 72, behavior: \"smooth\" })\n }\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: \"1px solid var(--nexus-widget-border, #E8E8E7)\",\n borderRadius: \"999px\",\n bottom: \"6px\",\n boxShadow: \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n display: \"flex\",\n height: \"22px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"22px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n );\n}\n\nfunction SwapReceiptPanel({\n entry,\n onDone,\n}: {\n entry: SwapHistoryEntry;\n onDone: () => void;\n}) {\n const [showSourceDetails, setShowSourceDetails] = useState(false);\n const destination = entry.intentData?.destination;\n const isFailed = entry.status === \"failed\";\n const isTimeout = entry.status === \"timeout\";\n const isDeposit = entry.mode === \"deposit\";\n const isSend = entry.mode === \"send\";\n const isRecipientTransfer = isSend || Boolean(entry.recipientAddress);\n const tokenSymbol = destination?.token.symbol || entry.toToken?.symbol || \"\";\n const chainName = getShortChainName(\n destination?.chain.id ?? entry.toToken?.chainId,\n destination?.chain.name || entry.toToken?.chainName || \"\"\n );\n const depositVenue =\n entry.opportunity?.title || entry.opportunity?.protocol || chainName;\n const amount = destination?.amount || \"\";\n const destinationLogo =\n destination?.token.logo ||\n entry.toToken?.logo ||\n entry.opportunity?.tokenLogo ||\n (isDeposit ? entry.opportunity?.logo : undefined);\n const requestedExactOutAmount =\n (isDeposit || isSend) && entry.requestedToAmount\n ? entry.requestedToAmount\n : undefined;\n const requestedExactOutValue =\n (isDeposit || isSend) && entry.requestedToValue\n ? entry.requestedToValue\n : undefined;\n const value = requestedExactOutValue || destination?.value;\n const displayAmount = requestedExactOutAmount || amount;\n const showIntentExplorer = hasValidIntentExplorer(entry);\n const intentLabel = entry.intentId\n ? `Intent #${entry.intentId}`\n : \"View Explorer\";\n const sourceRows = getSourceRows(entry);\n const sourceCount = sourceRows.length;\n const sourceTotalUsd = sourceRows.reduce(\n (sum, source) => sum.plus(parseDecimalLoose(source.value) ?? 0),\n new Decimal(0)\n );\n const defaultSwapFailureHeadline = entry.autoRefundAvailable\n ? \"Swap Failed. Refund Initiated\"\n : \"Swap Failed\";\n const entryFailureMessage =\n entry.status === \"timeout\" ? TIMEOUT_LABEL : entry.failureMessage;\n const storedFailureMessage =\n !entry.autoRefundAvailable && entryFailureMessage?.includes(\"Refund\")\n ? undefined\n : entryFailureMessage;\n const failureHeadline =\n storedFailureMessage ||\n (isDeposit\n ? \"Deposit failed. Funds are in your wallet\"\n : isRecipientTransfer\n ? \"Send failed. Funds are in your wallet\"\n : defaultSwapFailureHeadline);\n const failureDescription = isFailed ? entry.failureDescription : undefined;\n const timeoutHeadline = TIMEOUT_LABEL;\n const timeoutDescription = isTimeout\n ? entry.failureDescription ||\n \"This transaction is still pending. Check the intent explorer for the latest status.\"\n : undefined;\n const receiptLocation = isDeposit ? depositVenue : chainName;\n const receiptSummary = receiptLocation ? `on ${receiptLocation}` : \"\";\n\n return (\n \n \n \n \n \n {isFailed ? \"x\" : isTimeout ? \"!\" : \"✓\"}\n \n \n
\n {isTimeout\n ? timeoutHeadline\n : isFailed\n ? failureHeadline\n : isDeposit\n ? \"You deposited\"\n : isRecipientTransfer\n ? \"You sent\"\n : \"You received\"}\n
\n {(failureDescription || timeoutDescription) && (\n \n {failureDescription || timeoutDescription}\n \n )}\n \n {displayAmount ? formatTokenDisplay(displayAmount) : \"--\"}\n \n {tokenSymbol}\n \n \n
\n ≈ {formatUsdDisplay(value)}\n
\n {receiptSummary && (\n \n {receiptSummary}\n \n )}\n \n\n \n \n \n {isDeposit || isSend ? \"You Paid\" : \"You Swapped\"}\n \n \n \n {formatUsdDisplay(sourceTotalUsd)}\n \n setShowSourceDetails((current) => !current)}\n style={{\n alignItems: \"center\",\n background: \"transparent\",\n border: \"none\",\n color: \"var(--foreground-brand)\",\n cursor: \"pointer\",\n display: \"inline-flex\",\n fontFamily: uiFont,\n fontSize: \"12px\",\n gap: \"4px\",\n padding: 0,\n }}\n type=\"button\"\n >\n {showSourceDetails\n ? \"Hide Details\"\n : `${sourceCount} asset${sourceCount === 1 ? \"\" : \"s\"}`}\n \n \n \n \n \n
\n \n
\n \n {isRecipientTransfer && entry.recipientAddress && (\n \n \n Recipient\n \n \n \n )}\n {showIntentExplorer && (\n \n \n Intent Explorer\n \n \n {intentLabel} ↗\n \n \n )}\n {entry.finalExplorerUrl && (\n \n \n Final Transaction\n \n \n View Explorer ↗\n \n \n )}\n \n \n Total Fees\n \n \n {formatUsdDisplay(entry.feeUsd)}\n \n \n \n\n \n Done\n \n \n );\n}\n\nconst getRelativeTime = (time: number, now: number) => {\n const seconds = Math.max(1, Math.floor((now - time) / 1000));\n if (seconds < 60) return `${seconds} second${seconds === 1 ? \"\" : \"s\"} ago`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes} minute${minutes === 1 ? \"\" : \"s\"} ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours} hour${hours === 1 ? \"\" : \"s\"} ago`;\n const days = Math.floor(hours / 24);\n return `${days} day${days === 1 ? \"\" : \"s\"} ago`;\n};\n\nfunction HistoryStatusPill({ status }: { status: SwapHistoryStatus }) {\n const config =\n status === \"fulfilled\"\n ? { label: \"Fulfilled\", bg: \"var(--nexus-widget-success-background, #E8F6EF)\", fg: \"var(--nexus-widget-success-text, #168A47)\" }\n : status === \"pending\"\n ? { label: \"Pending\", bg: \"var(--nexus-widget-warning-background, #FFF3DE)\", fg: \"var(--nexus-widget-warning-text, #B7791F)\" }\n : status === \"timeout\"\n ? { label: TIMEOUT_LABEL, bg: \"var(--nexus-widget-warning-background, #FFF3DE)\", fg: \"var(--nexus-widget-warning-text, #B7791F)\" }\n : status === \"refund-initiated\"\n ? { label: \"Refund Initiated\", bg: \"var(--nexus-widget-warning-background, #FFF3DE)\", fg: \"var(--nexus-widget-warning-text, #B7791F)\" }\n : { label: \"Failed\", bg: \"var(--nexus-widget-error-background, #FFE6EA)\", fg: \"var(--nexus-widget-error-text, #E92C2C)\" };\n\n return (\n \n {config.label}\n \n );\n}\n\nfunction SwapHistoryPanel({\n entries,\n now,\n}: {\n entries: SwapHistoryEntry[];\n now: number;\n}) {\n if (entries.length === 0) {\n return (\n \n \n \n ↻\n \n \n \n No transactions yet\n \n \n Your transaction history will appear here once you make your first\n swap, deposit, or send.\n \n \n );\n }\n\n const sortedEntries = sortSwapHistoryEntries(entries);\n const shouldScroll = sortedEntries.length > 5;\n\n return (\n \n {sortedEntries.map((entry) => {\n const destination = entry.intentData?.destination;\n const destinationLogo =\n destination?.token.logo ||\n entry.toToken?.logo ||\n entry.opportunity?.tokenLogo ||\n \"\";\n const destinationChainLogo =\n destination?.chain.logo || entry.toToken?.chainLogo || \"\";\n const destinationChainName = getShortChainName(\n destination?.chain.id ?? entry.toToken?.chainId,\n destination?.chain.name || entry.toToken?.chainName || \"\"\n );\n const destinationSymbol =\n destination?.token.symbol || entry.toToken?.symbol || \"\";\n const destinationValue =\n (entry.mode === \"deposit\" || entry.mode === \"send\") &&\n entry.requestedToValue\n ? entry.requestedToValue\n : destination?.value;\n const destinationAmount =\n (entry.mode === \"deposit\" || entry.mode === \"send\") &&\n entry.requestedToAmount\n ? entry.requestedToAmount\n : destination?.amount || \"\";\n const canShowRefund =\n entry.status === \"failed\" && Boolean(entry.autoRefundAvailable);\n const status = canShowRefund ? \"refund-initiated\" : entry.status;\n const sourceRows = getSourceRows(entry);\n const historyExplorerUrl = getHistoryExplorerUrl(entry);\n\n return (\n \n \n \n \n
\n \n {destinationAmount\n ? formatTokenDisplay(destinationAmount)\n : \"--\"}\n \n {destinationSymbol}\n \n
\n \n ≈ {formatUsdDisplay(destinationValue)}\n \n \n \n \n \n \n {getRelativeTime(entry.createdAt ?? entry.startedAt, now)}\n \n \n \n\n {canShowRefund && (\n \n \n Refund Initiated\n \n \n )}\n\n \n \n {sourceRows.length > 0 && (\n \n )}\n \n →\n \n \n \n {historyExplorerUrl && (\n \n \n View\n \n \n \n \n \n \n )}\n \n \n );\n })}\n \n );\n}\n\n// ---------------------------------------------------------------------------\n// NexusWidget\n// ---------------------------------------------------------------------------\n\nexport function NexusWidget(props: NexusWidgetProps) {\n const resolvedTheme = useResolvedNexusWidgetTheme(\n resolveNexusWidgetTheme(props.config.theme, props.config.appearance?.mode)\n );\n const primaryColor =\n normalizeNexusWidgetPrimaryColor(props.config.appearance?.primaryColor) ??\n NEXUS_WIDGET_DEFAULT_PRIMARY_COLOR;\n const primaryForeground = getReadableTextColor(primaryColor);\n const themeStyle = useMemo(\n () => ({\n ...getNexusWidgetThemeStyle(resolvedTheme === \"dark\"),\n \"--nexus-widget-primary\": primaryColor,\n \"--nexus-widget-primary-foreground\": primaryForeground,\n \"--foreground-brand\": primaryColor,\n \"--interactive-button-primary-background\": primaryColor,\n \"--interactive-button-primary-foreground\": primaryForeground,\n }),\n [resolvedTheme, primaryColor, primaryForeground]\n );\n return (\n \n \n
\n Something went wrong\n
\n \n An unexpected error occurred. Please refresh the page or try\n resetting the widget.\n \n window.location.reload()}\n style={{\n backgroundColor: \"var(--foreground-brand)\",\n border: \"none\",\n borderRadius: \"8px\",\n color: \"var(--nexus-widget-primary-foreground, #FFFFFE)\",\n cursor: \"pointer\",\n fontSize: \"15px\",\n fontWeight: 500,\n padding: \"8px 16px\",\n transition: \"background-color 0.15s ease-out\",\n }}\n type=\"button\"\n >\n Reload Page\n \n \n }\n >\n \n \n
\n );\n}\n\nfunction NexusWidgetInner({\n config: rawConfig,\n embed = true,\n className,\n connectedAddress,\n open: controlledOpen,\n onOpenChange,\n defaultOpen = false,\n onComplete,\n onConnectClick,\n onStart,\n onError,\n onReceiveAssetChange,\n onClose,\n onConnectWallet,\n}: NexusWidgetProps) {\n const themeStyle = useNexusWidgetThemeStyle();\n const {\n nexusSDK,\n bridgableBalance,\n swapBalance,\n swapBalanceLoading,\n getFiatValue,\n resolveTokenUsdRate,\n swapSupportedChainsAndTokens,\n supportedChainsAndTokens,\n fetchSwapBalance,\n handleInit,\n swapIntent: providerSwapIntent,\n network,\n loading: nexusLoading,\n } = useNexus();\n const appConfig = useMemo(\n () => ({\n nexusNetwork: network ?? \"mainnet\",\n }),\n [network]\n );\n const isSwapBalancePending =\n Boolean(nexusSDK) && (swapBalanceLoading || swapBalance === null);\n\n const normalizedWidgetConfig = useMemo(\n () => normalizeNexusWidgetConfig(rawConfig),\n [rawConfig]\n );\n const config = normalizedWidgetConfig.config;\n const activeMode = normalizedWidgetConfig.activeMode;\n const amountInputConfig = normalizedWidgetConfig.amountInput;\n const appearanceConfig = normalizedWidgetConfig.appearance;\n const configuredDepositOptions = normalizedWidgetConfig.depositOptions;\n const isConfiguredAmountFixed = normalizedWidgetConfig.isAmountFixed;\n const isConfiguredRecipientLocked =\n normalizedWidgetConfig.isRecipientLocked;\n const primaryColor = normalizeNexusWidgetPrimaryColor(\n appearanceConfig?.primaryColor\n );\n const primaryButtonBackground =\n primaryColor ?? NEXUS_WIDGET_DEFAULT_PRIMARY_COLOR;\n const primaryButtonForeground = getReadableTextColor(\n primaryButtonBackground\n );\n const theme = useMemo(\n () => ({\n ...nexusWidgetTheme,\n colors: {\n ...nexusWidgetTheme.colors,\n primary: \"var(--foreground-brand)\",\n primaryText: \"var(--foreground-brand)\",\n },\n }),\n [primaryColor]\n );\n const configuredDeposit = getConfiguredDeposit(config);\n const configuredDepositIdentity = getDepositConfigIdentity(configuredDeposit);\n const configuredDestinationTokenOptions = useMemo(() => {\n const destination = rawConfig.destination;\n const destinationChainId = getConfiguredDestinationChainId(destination);\n const destinationTokens =\n rawConfig.mode === \"deposit\"\n ? configuredDepositOptions.map(toSwapTokenOptionFromDepositConfig)\n : destination?.tokens && destinationChainId\n ? destination.tokens\n .map((token) =>\n toSwapTokenOptionFromConfiguredDestinationToken(\n token,\n destinationChainId\n )\n )\n .filter((token): token is SwapTokenOption => Boolean(token))\n : [];\n\n const tokensByKey = new Map();\n for (const token of destinationTokens) {\n tokensByKey.set(getTokenSelectionKey(token), token);\n }\n return Array.from(tokensByKey.values());\n }, [configuredDepositOptions, rawConfig.destination]);\n if (activeMode === \"deposit\" && !configuredDeposit) {\n throw new Error(\n \"NexusWidget deposit mode requires destination.chain, at least one destination token, depositAddress, and executeDeposit.\"\n );\n }\n const showCloseButton = !embed && Boolean(onClose);\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isControlledOpen = controlledOpen !== undefined;\n const isModalOpen = isControlledOpen ? controlledOpen : internalOpen;\n\n // Preload receive tokens once SDK is available\n useEffect(() => {\n if (nexusSDK) {\n console.log(\n \"[preloadReceiveTokens] Calling preloadReceiveTokens from NexusWidget useEffect (nexusSDK available)\"\n );\n preloadReceiveTokens();\n }\n }, [nexusSDK]);\n\n const {\n address: accountAddress,\n connector,\n status: walletStatus,\n } = useAccount();\n const {\n connectors,\n connectAsync,\n isPending: isWalletConnectPending,\n } = useConnect();\n const { data: walletClient } = useWalletClient();\n const { data: connectorClient } = useConnectorClient();\n const publicClient = usePublicClient();\n const walletClientAddress = walletClient?.account?.address;\n const ownerAddress =\n connectedAddress &&\n isAddress(connectedAddress) &&\n connectedAddress.toLowerCase() !== zeroAddress\n ? connectedAddress\n : accountAddress &&\n isAddress(accountAddress) &&\n accountAddress.toLowerCase() !== zeroAddress\n ? accountAddress\n : walletClientAddress &&\n isAddress(walletClientAddress) &&\n walletClientAddress.toLowerCase() !== zeroAddress\n ? walletClientAddress\n : undefined;\n const getEffectiveWalletProvider = useCallback(\n async (activeConnector = connector) => {\n let connectorProvider: unknown;\n try {\n connectorProvider = await activeConnector?.getProvider();\n } catch {\n connectorProvider = undefined;\n }\n\n const connectorClientProvider = connectorClient\n ? {\n request: (args: unknown) => connectorClient.request(args as any),\n }\n : undefined;\n const walletClientProvider = walletClient\n ? {\n request: (args: unknown) => walletClient.request(args as any),\n }\n : undefined;\n const windowProvider =\n typeof window !== \"undefined\"\n ? (window as Window & { ethereum?: EthereumProvider }).ethereum\n : undefined;\n const effectiveProvider =\n connectorProvider &&\n typeof (connectorProvider as EthereumProvider).request === \"function\"\n ? (connectorProvider as EthereumProvider)\n : (connectorClientProvider ?? walletClientProvider ?? windowProvider);\n\n return effectiveProvider &&\n typeof effectiveProvider.request === \"function\"\n ? (effectiveProvider as EthereumProvider)\n : undefined;\n },\n [connector, connectorClient, walletClient]\n );\n const historyStorageKey = getSwapHistoryStorageKey(ownerAddress);\n\n useEffect(() => {\n if (walletStatus !== \"connected\" || !ownerAddress) {\n return;\n }\n\n let cancelled = false;\n void (async () => {\n const effectiveProvider = await getEffectiveWalletProvider();\n if (cancelled || !effectiveProvider) {\n return;\n }\n await handleInit(effectiveProvider, ownerAddress);\n })().catch((error) => {\n if (!cancelled) {\n console.error(\"Unable to initialize Nexus for wallet address:\", error);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [getEffectiveWalletProvider, handleInit, ownerAddress, walletStatus]);\n\n // Global form state\n const [amount, setAmount] = useState(\"\");\n const [recipientAddress, setRecipientAddress] = useState(\"\");\n const [editingAssetIndex, setEditingAssetIndex] = useState(\n null\n );\n const [txError, setTxError] = useState(null);\n const [walletActionPending, setWalletActionPending] = useState(false);\n const defaultRecipientAddress = ownerAddress ?? \"\";\n const effectiveRecipientAddress =\n activeMode === \"swap\"\n ? recipientAddress || defaultRecipientAddress\n : recipientAddress;\n const hasSameOwnerSendRecipient =\n activeMode === \"send\" &&\n Boolean(\n ownerAddress &&\n recipientAddress &&\n isAddress(recipientAddress) &&\n recipientAddress.toLowerCase() === ownerAddress.toLowerCase()\n );\n const hasCustomSwapRecipient =\n activeMode === \"swap\" &&\n Boolean(\n recipientAddress &&\n (!defaultRecipientAddress ||\n recipientAddress.toLowerCase() !==\n defaultRecipientAddress.toLowerCase())\n );\n const transferRecipientAddress =\n activeMode === \"send\"\n ? recipientAddress\n : hasCustomSwapRecipient\n ? recipientAddress\n : undefined;\n\n // Swap-specific\n const [swapType, setSwapType] = useState(\"exactIn\");\n const [swapStep, setSwapStep] = useState(\"idle\");\n const drawerCloseTimerRef = useRef | null>(\n null\n );\n const terminalBalanceRefreshTimerRef = useRef | null>(null);\n const [closingDrawerStep, setClosingDrawerStep] = useState(\n null\n );\n const rootContentRef = useRef(null);\n const [rootContentHeight, setRootContentHeight] = useState(\n null\n );\n const rootContentHeightRef = useRef(null);\n const [hasMeasuredRootContent, setHasMeasuredRootContent] = useState(false);\n const [shouldAnimateRootHeight, setShouldAnimateRootHeight] = useState(false);\n const [isPreviewTransitioning, setIsPreviewTransitioning] = useState(false);\n const rootHeightTransitionTimerRef = useRef | null>(null);\n const [fromTokens, setFromTokens] = useState([]);\n const [sourceSelectionTouched, setSourceSelectionTouched] = useState(false);\n const [sourceSelectionRevision, setSourceSelectionRevision] = useState(0);\n const [\n sourceSelectionRequiredUsdDisplay,\n setSourceSelectionRequiredUsdDisplay,\n ] = useState(undefined);\n const [sourcePickerDraftTokens, setSourcePickerDraftTokens] = useState<\n SwapTokenOption[] | null\n >(null);\n const sourcePickerDraftTokensRef = useRef(null);\n const sourcePickerDraftDepositFilterRef = useRef(\"all\");\n const sourcePickerDraftTouchedRef = useRef(false);\n const sourcePickerDraftModeRef = useRef<\"all\" | \"selected\">(\"all\");\n const [exactOutQuoteSourceMode, setExactOutQuoteSourceMode] = useState<\n \"all\" | \"selected\"\n >(\"all\");\n const exactOutQuoteSourceModeRef = useRef<\"all\" | \"selected\">(\"all\");\n const [toToken, setToToken] = useState(\n undefined\n );\n const [fromTokensQuoteKey, setFromTokensQuoteKey] = useState(\"\");\n\n useEffect(() => {\n const key = getSourceTokensQuoteKey(\n activeMode === \"swap\" && swapType === \"exactIn\"\n ? getReadyExactInSourceTokens(fromTokens)\n : fromTokens\n );\n setFromTokensQuoteKey(key);\n }, [activeMode, swapType, fromTokens]);\n const toTokenQuoteKey = getTokenQuoteKey(toToken);\n const appliedTokenPrefillRef = useRef(null);\n\n useEffect(() => {\n if (!toToken?.chainId || !toToken.contractAddress) return;\n\n let active = true;\n const selectedTokenKey = getTokenSelectionKey(toToken);\n const applyLoadedReceiveToken = () => {\n if (!active) return;\n const loadedToken = getCachedReceiveTokenMatch(toToken);\n if (!loadedToken) return;\n\n setToToken((current) => {\n if (!current || getTokenSelectionKey(current) !== selectedTokenKey) {\n return current;\n }\n\n const chainMeta = current.chainId\n ? CHAIN_METADATA[current.chainId]\n : undefined;\n const next = {\n ...current,\n chainLogo:\n loadedToken.chainLogo || current.chainLogo || chainMeta?.logo,\n chainName: getShortChainName(\n current.chainId,\n loadedToken.chainName || current.chainName || chainMeta?.name\n ),\n decimals: loadedToken.decimals ?? current.decimals,\n logo: loadedToken.logo || current.logo,\n name: loadedToken.name || current.name,\n priceUSD: loadedToken.priceUSD ?? current.priceUSD,\n symbol: loadedToken.symbol || current.symbol,\n };\n\n if (\n current.decimals === next.decimals &&\n current.chainLogo === next.chainLogo &&\n current.chainName === next.chainName &&\n current.logo === next.logo &&\n current.name === next.name &&\n current.priceUSD === next.priceUSD &&\n current.symbol === next.symbol\n ) {\n return current;\n }\n\n return next;\n });\n };\n\n applyLoadedReceiveToken();\n const receiveTokensPromise = preloadReceiveTokens();\n receiveTokensPromise?.then(applyLoadedReceiveToken).catch((error) => {\n if (active) {\n console.warn(\"Unable to refresh receive token metadata\", error);\n }\n });\n\n return () => {\n active = false;\n };\n }, [\n toToken?.chainId,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.symbol,\n ]);\n\n const setExactOutQuoteSourceModeValue = useCallback(\n (mode: \"all\" | \"selected\") => {\n exactOutQuoteSourceModeRef.current = mode;\n setExactOutQuoteSourceMode(mode);\n },\n []\n );\n\n useEffect(() => {\n if (!nexusSDK) return;\n void fetchSwapBalance();\n }, [fetchSwapBalance, nexusSDK]);\n\n useEffect(() => {\n setSourceSelectionTouched(false);\n setExactOutQuoteSourceModeValue(\"all\");\n }, [activeMode, setExactOutQuoteSourceModeValue]);\n\n useEffect(() => {\n if (activeMode !== \"swap\") return;\n\n setRecipientAddress((current) => {\n if (!defaultRecipientAddress) return current ? \"\" : current;\n return current.toLowerCase() === defaultRecipientAddress.toLowerCase()\n ? current\n : defaultRecipientAddress;\n });\n }, [activeMode, defaultRecipientAddress]);\n\n const {\n steps,\n seed,\n onStepsList,\n onStepComplete,\n reset: resetSteps,\n } = useTransactionSteps();\n const [progressEvents, setProgressEvents] = useState(\n []\n );\n const progressEventsRef = useRef([]);\n const swapStepsListRef = useRef([]);\n const [failedProgressStep, setFailedProgressStep] = useState<\n SwapStepType | BridgeStepType | null\n >(null);\n const [explorerUrls, setExplorerUrls] = useState<{\n sourceExplorerUrl: string | null;\n destinationExplorerUrl: string | null;\n }>({ sourceExplorerUrl: null, destinationExplorerUrl: null });\n const swapRunIdRef = useRef(0);\n\n const widgetSessionIdRef = useRef(\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(36).slice(2)}`\n );\n const widgetAttemptIdRef = useRef(null);\n const widgetOpenedTsRef = useRef(Date.now());\n const previewViewedTsRef = useRef(null);\n const previewConfirmedTsRef = useRef(null);\n const attemptCountRef = useRef(0);\n const fundsMovedRef = useRef(false);\n const intentUrlRef = useRef(null);\n const hadSimulationSuccessRef = useRef(false);\n const hadPreviewViewedRef = useRef(false);\n const widgetOpenedFiredRef = useRef(false);\n const reachedTerminalRef = useRef(false);\n const lastIntentSourceTokensRef = useRef([]);\n const lastAutoIntentSourceTokensRef = useRef([]);\n const immediateQuoteAfterSourceEditRef = useRef(false);\n const amountEnteredLastValueRef = useRef(\"\");\n const lastInputMethodRef = useRef<\n | \"typed\"\n | \"percent_20\"\n | \"percent_25\"\n | \"percent_50\"\n | \"percent_75\"\n | \"percent_max\"\n >(\"typed\");\n const prevSourceTouchedRef = useRef(false);\n const previousAutoSourceCountRef = useRef(0);\n const analyticsRef = useRef<{\n track: (event: string, properties?: Record) => void;\n } | null>(null);\n const selectedOpportunityRef = useRef(\n undefined\n );\n\n const newAttemptId = useCallback(() => {\n return typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n }, []);\n\n const rotateAttempt = useCallback(() => {\n widgetAttemptIdRef.current = newAttemptId();\n previewViewedTsRef.current = null;\n previewConfirmedTsRef.current = null;\n fundsMovedRef.current = false;\n intentUrlRef.current = null;\n hadSimulationSuccessRef.current = false;\n hadPreviewViewedRef.current = false;\n reachedTerminalRef.current = false;\n }, [newAttemptId]);\n const [intentToAmount, setIntentToAmount] = useState(\n undefined\n );\n const [intentFeeUsd, setIntentFeeUsd] = useState(\n undefined\n );\n const [intentLoading, setIntentLoading] = useState(false);\n const [quoteRefreshing, setQuoteRefreshing] = useState(false);\n const [receiveMaxCalculating, setReceiveMaxCalculating] = useState(false);\n const [maxCalculationPercent, setMaxCalculationPercent] = useState<\n number | null\n >(null);\n const intentDestinationUsdRateCacheRef = useRef<\n Record\n >({});\n const intentSymbolUsdRateCacheRef = useRef<\n Record\n >({});\n const predictiveQuoteCacheRef = useRef<\n Record\n >({});\n const predictiveQuoteRunRef = useRef(0);\n const latestIntentFetchRunIdRef = useRef(0);\n const intentFetchTimingRef = useRef(null);\n const intentUiRenderLoggedRunIdRef = useRef(null);\n const [intentFetchTiming, setIntentFetchTiming] =\n useState(null);\n const [predictiveQuote, setPredictiveQuote] =\n useState(null);\n const maxPercentRunRef = useRef(0);\n const [previewQuoteRefreshing, setPreviewQuoteRefreshing] = useState(false);\n const [quoteRefreshProgress, setQuoteRefreshProgress] = useState(0);\n const [quoteRefreshSecondsRemaining, setQuoteRefreshSecondsRemaining] =\n useState(0);\n const [intentData, setIntentData] = useState(null);\n const [swapQuoteIssue, setSwapQuoteIssue] = useState(\n null\n );\n const [receiveAmountIssue, setReceiveAmountIssue] =\n useState(null);\n const receiveAmountIssueRef = useRef(null);\n const receiveAmountIssueKeyRef = useRef(\"\");\n const [transferExplorerUrl, setTransferExplorerUrl] = useState(\n null\n );\n const swapStepRef = useRef(swapStep);\n const syncingIntentSourcesRef = useRef(false);\n const lastSwapIntentRefreshAtRef = useRef(0);\n const [destinationBalance, setDestinationBalance] = useState(\n null\n );\n const [swapHistory, setSwapHistory] = useState(() =>\n readSwapHistoryFromStorage(historyStorageKey)\n );\n const [currentSwapId, setCurrentSwapId] = useState(null);\n const [historyNow, setHistoryNow] = useState(() => Date.now());\n const currentSwapIdRef = useRef(null);\n const currentSwapStartedAtRef = useRef(0);\n const historyStorageKeyRef = useRef(historyStorageKey);\n const skipNextHistoryPersistRef = useRef(false);\n const explorerUrlsRef = useRef<{\n sourceExplorerUrl: string | null;\n destinationExplorerUrl: string | null;\n }>({ sourceExplorerUrl: null, destinationExplorerUrl: null });\n const activeQuoteInputKeyRef = useRef(\"\");\n\n // Ref to store swap intent hook allow/deny callbacks\n const swapIntentRef = useRef<{\n intent?: SwapIntentData;\n allow: () => void;\n deny: () => void;\n refresh: () => Promise;\n runId?: number;\n quoteInputKey?: string;\n } | null>(null);\n\n const startIntentFetchTiming = useCallback(\n ({\n background,\n operation,\n quoteInputKey,\n runId,\n }: {\n background: boolean;\n operation: string;\n quoteInputKey: string;\n runId: number;\n }) => {\n const startTimeMs = Date.now();\n const timing: IntentFetchTiming = {\n background,\n operation,\n quoteInputKey,\n runId,\n startTimeMs,\n walletAddress: ownerAddress ?? null,\n };\n\n latestIntentFetchRunIdRef.current = runId;\n intentFetchTimingRef.current = timing;\n intentUiRenderLoggedRunIdRef.current = null;\n setIntentFetchTiming(timing);\n console.log(\"[NexusWidget] intent fetch start\", {\n runId,\n walletAddress: timing.walletAddress,\n operation,\n quoteInputKey,\n background,\n dateNow: startTimeMs,\n date: new Date(startTimeMs),\n });\n return timing;\n },\n [ownerAddress]\n );\n\n const finishIntentFetchTiming = useCallback(\n (runId: number, status: \"resolved\" | \"failed\" = \"resolved\") => {\n const timing = intentFetchTimingRef.current;\n if (!timing || timing.runId !== runId) return;\n if (timing.endTimeMs !== undefined) return;\n\n const endTimeMs = Date.now();\n if (latestIntentFetchRunIdRef.current !== runId) {\n return;\n }\n\n const fetchDurationMs = endTimeMs - timing.startTimeMs;\n const completedTiming: IntentFetchTiming = {\n ...timing,\n endTimeMs,\n fetchDurationMs,\n };\n intentFetchTimingRef.current = completedTiming;\n setIntentFetchTiming(completedTiming);\n console.log(\"[NexusWidget] intent fetch end\", {\n runId,\n walletAddress: timing.walletAddress,\n operation: timing.operation,\n quoteInputKey: timing.quoteInputKey,\n status,\n dateNow: endTimeMs,\n date: new Date(endTimeMs),\n });\n console.log(\"[NexusWidget] intent fetch total\", {\n runId,\n walletAddress: timing.walletAddress,\n operation: timing.operation,\n quoteInputKey: timing.quoteInputKey,\n totalTimeSeconds: fetchDurationMs / 1000,\n elapsedMs: fetchDurationMs,\n dateNow: endTimeMs,\n });\n },\n []\n );\n\n useEffect(() => {\n swapStepRef.current = swapStep;\n }, [swapStep]);\n\n useEffect(() => {\n return () => {\n if (drawerCloseTimerRef.current) {\n clearTimeout(drawerCloseTimerRef.current);\n }\n if (terminalBalanceRefreshTimerRef.current) {\n clearTimeout(terminalBalanceRefreshTimerRef.current);\n }\n if (rootHeightTransitionTimerRef.current) {\n clearTimeout(rootHeightTransitionTimerRef.current);\n }\n };\n }, []);\n\n const isQuoteEditLocked = useCallback(\n () => swapStepRef.current === \"choose-swap-asset\",\n []\n );\n\n const getQuoteRequestDelay = useCallback(() => {\n if (immediateQuoteAfterSourceEditRef.current) {\n immediateQuoteAfterSourceEditRef.current = false;\n return 0;\n }\n return EXACT_OUT_INPUT_DEBOUNCE_MS;\n }, []);\n\n const startRootHeightTransition = useCallback(() => {\n setShouldAnimateRootHeight(true);\n if (rootHeightTransitionTimerRef.current) {\n clearTimeout(rootHeightTransitionTimerRef.current);\n }\n rootHeightTransitionTimerRef.current = setTimeout(() => {\n setShouldAnimateRootHeight(false);\n rootHeightTransitionTimerRef.current = null;\n }, ROOT_HEIGHT_TRANSITION_MS);\n }, []);\n\n const closeDrawerToIdle = useCallback(() => {\n const isDrawerStep =\n swapStep === \"choose-swap-asset\" ||\n swapStep === \"choose-receive-asset\" ||\n swapStep === \"enter-recipient\";\n\n if (!isDrawerStep) {\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n return;\n }\n\n if (drawerCloseTimerRef.current) {\n clearTimeout(drawerCloseTimerRef.current);\n }\n\n setClosingDrawerStep(swapStep);\n drawerCloseTimerRef.current = setTimeout(() => {\n if (\n swapStep === \"choose-swap-asset\" ||\n swapStep === \"choose-receive-asset\"\n ) {\n startRootHeightTransition();\n }\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n setClosingDrawerStep(null);\n drawerCloseTimerRef.current = null;\n }, DRAWER_CLOSE_MS);\n }, [startRootHeightTransition, swapStep]);\n\n const openDrawerStep = useCallback((nextStep: SwapStep) => {\n if (drawerCloseTimerRef.current) {\n clearTimeout(drawerCloseTimerRef.current);\n drawerCloseTimerRef.current = null;\n }\n if (\n nextStep === \"choose-swap-asset\" ||\n nextStep === \"choose-receive-asset\"\n ) {\n startRootHeightTransition();\n }\n setClosingDrawerStep(null);\n swapStepRef.current = nextStep;\n setSwapStep(nextStep);\n }, [startRootHeightTransition]);\n\n const syncRootContentHeight = useCallback((animate = false) => {\n const element = rootContentRef.current;\n if (!element) return;\n\n const nextHeight = Math.ceil(\n Math.max(element.getBoundingClientRect().height, element.scrollHeight)\n );\n if (nextHeight <= 0) return;\n\n if (rootContentHeightRef.current === nextHeight) {\n setHasMeasuredRootContent(true);\n return;\n }\n\n rootContentHeightRef.current = nextHeight;\n setShouldAnimateRootHeight(animate);\n if (rootHeightTransitionTimerRef.current) {\n clearTimeout(rootHeightTransitionTimerRef.current);\n rootHeightTransitionTimerRef.current = null;\n }\n if (animate) {\n rootHeightTransitionTimerRef.current = setTimeout(() => {\n setShouldAnimateRootHeight(false);\n rootHeightTransitionTimerRef.current = null;\n }, ROOT_HEIGHT_TRANSITION_MS);\n }\n setRootContentHeight(nextHeight);\n setHasMeasuredRootContent(true);\n }, []);\n\n useLayoutEffect(() => {\n syncRootContentHeight(true);\n\n const element = rootContentRef.current;\n if (!element || typeof ResizeObserver === \"undefined\") return;\n\n let frame = 0;\n const observer = new ResizeObserver(() => {\n if (frame) {\n window.cancelAnimationFrame(frame);\n }\n frame = window.requestAnimationFrame(() => {\n syncRootContentHeight(false);\n });\n });\n\n observer.observe(element);\n\n return () => {\n if (frame) {\n window.cancelAnimationFrame(frame);\n }\n observer.disconnect();\n };\n }, [activeMode, swapStep, syncRootContentHeight]);\n\n useEffect(() => {\n currentSwapIdRef.current = currentSwapId;\n }, [currentSwapId]);\n\n useEffect(() => {\n if (historyStorageKeyRef.current === historyStorageKey) return;\n historyStorageKeyRef.current = historyStorageKey;\n skipNextHistoryPersistRef.current = true;\n setSwapHistory(readSwapHistoryFromStorage(historyStorageKey));\n }, [historyStorageKey]);\n\n useEffect(() => {\n if (skipNextHistoryPersistRef.current) {\n skipNextHistoryPersistRef.current = false;\n return;\n }\n\n writeSwapHistoryToStorage(historyStorageKey, swapHistory);\n }, [historyStorageKey, swapHistory]);\n\n useEffect(() => {\n if (swapStep !== \"history\") return;\n const timer = window.setInterval(() => setHistoryNow(Date.now()), 30000);\n return () => window.clearInterval(timer);\n }, [swapStep]);\n\n const normalizeAddress = (value?: string | null) =>\n (value ?? \"\").toLowerCase();\n\n const getTokenLookupAddress = (value?: string | null) => {\n if (!value) return \"\";\n return isNativeTokenAddress(value) ? zeroAddress : value.toLowerCase();\n };\n\n const findBalanceTokenLogo = (\n chainId?: number,\n contractAddress?: string,\n symbol?: string\n ) => {\n if (!chainId) return \"\";\n const lookupAddress = getTokenLookupAddress(contractAddress);\n const lookupSymbol = symbol?.toUpperCase();\n let symbolMatchLogo = \"\";\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n if (breakdown.chain?.id !== chainId) continue;\n const breakdownAddress = getTokenLookupAddress(\n breakdown.contractAddress\n );\n const addressMatches =\n lookupAddress && breakdownAddress === lookupAddress;\n const symbolMatches =\n lookupSymbol &&\n [breakdown.symbol, asset.symbol]\n .filter(Boolean)\n .some((candidate) => candidate.toUpperCase() === lookupSymbol);\n const logo = getLogoFromMetadata(breakdown) || getLogoFromMetadata(asset);\n\n if (addressMatches && logo) return logo;\n if (!symbolMatchLogo && symbolMatches && logo) {\n symbolMatchLogo = logo;\n }\n }\n }\n\n return symbolMatchLogo;\n };\n\n const findSupportedTokenLogo = (\n chains: any[] | null | undefined,\n chainId?: number,\n contractAddress?: string,\n symbol?: string\n ) => {\n if (!chainId) return \"\";\n const chain = chains?.find(\n (item: any) => Number(item?.id ?? item?.chainId) === chainId\n );\n const tokens = chain?.tokens ?? chain?.assets ?? [];\n const lookupAddress = getTokenLookupAddress(contractAddress);\n const lookupSymbol = symbol?.toUpperCase();\n\n const addressMatch =\n lookupAddress &&\n tokens.find((token: any) => {\n const tokenAddress = getTokenLookupAddress(\n token?.contractAddress ?? token?.address ?? token?.tokenAddress\n );\n return tokenAddress === lookupAddress;\n });\n const symbolMatch =\n lookupSymbol &&\n tokens.find((token: any) => {\n const tokenSymbol = (token?.symbol ?? token?.tokenSymbol ?? \"\")\n .toString()\n .toUpperCase();\n return tokenSymbol === lookupSymbol;\n });\n\n return getLogoFromMetadata(addressMatch) || getLogoFromMetadata(symbolMatch);\n };\n\n const resolveTokenLogo = (\n token:\n | {\n address?: string;\n contractAddress?: string;\n logo?: string;\n symbol?: string;\n tokenAddress?: string;\n tokenSymbol?: string;\n }\n | undefined,\n chainId?: number\n ) => {\n const explicitLogo = getLogoFromMetadata(token);\n if (explicitLogo) return explicitLogo;\n\n const contractAddress =\n token?.contractAddress ?? token?.address ?? token?.tokenAddress;\n const symbol = token?.symbol ?? token?.tokenSymbol;\n const citreaToken = findCitreaReceiveToken({\n address: contractAddress,\n chainId,\n symbol,\n });\n const tokenMeta = symbol\n ? TOKEN_METADATA[symbol as keyof typeof TOKEN_METADATA]\n : undefined;\n\n return (\n findBalanceTokenLogo(chainId, contractAddress, symbol) ||\n findSupportedTokenLogo(\n swapSupportedChainsAndTokens,\n chainId,\n contractAddress,\n symbol\n ) ||\n findSupportedTokenLogo(\n supportedChainsAndTokens,\n chainId,\n contractAddress,\n symbol\n ) ||\n citreaToken?.logo ||\n tokenMeta?.logo ||\n (contractAddress && isNativeTokenAddress(contractAddress)\n ? CHAIN_METADATA[chainId ?? 0]?.logo\n : \"\") ||\n \"\"\n );\n };\n\n const enrichIntentToken = <\n T extends {\n address?: string;\n contractAddress?: string;\n logo?: string;\n symbol?: string;\n tokenAddress?: string;\n tokenSymbol?: string;\n },\n >(\n token: T,\n chainId?: number\n ): T => {\n const logo = resolveTokenLogo(token, chainId);\n return logo && logo !== token.logo ? { ...token, logo } : token;\n };\n\n const enrichTokenOptionLogo = (\n token?: SwapTokenOption\n ): SwapTokenOption | undefined => {\n if (!token) return undefined;\n\n const chainMeta = token.chainId ? CHAIN_METADATA[token.chainId] : undefined;\n const logo = resolveTokenLogo(token, token.chainId);\n const next = {\n ...token,\n chainLogo: token.chainLogo || chainMeta?.logo,\n logo: token.logo || logo,\n };\n\n if (next.chainLogo === token.chainLogo && next.logo === token.logo) {\n return token;\n }\n\n return next;\n };\n\n const enrichSwapIntentTokenMetadata = (\n intent: SwapIntentData\n ): SwapIntentData => ({\n ...intent,\n destination: {\n ...intent.destination,\n token: enrichIntentToken(\n intent.destination.token,\n intent.destination.chain.id\n ),\n },\n sources: (intent.sources ?? []).map((source) => ({\n ...source,\n token: enrichIntentToken(source.token, source.chain.id),\n })),\n });\n\n const buildIntentSourceToken = (\n source: SwapIntentData[\"sources\"][number]\n ): SwapTokenOption => {\n let matchedAsset: any;\n let matchedBreakdown: any;\n const sourceAddress = normalizeAddress(source.token.contractAddress);\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n const addressMatches =\n normalizeAddress(breakdown.contractAddress) === sourceAddress;\n const symbolMatches =\n breakdown.symbol === source.token.symbol ||\n asset.symbol === source.token.symbol;\n if (\n breakdown.chain?.id === source.chain.id &&\n (addressMatches || symbolMatches)\n ) {\n matchedAsset = asset;\n matchedBreakdown = breakdown;\n break;\n }\n }\n if (matchedBreakdown) break;\n }\n\n const chainMeta = CHAIN_METADATA[source.chain.id];\n const sourceValue = Number((source as any).value ?? 0);\n const isNativeSource = isNativeTokenAddress(source.token.contractAddress);\n const nativeCurrency = chainMeta?.nativeCurrency;\n const sourceSymbol =\n isNativeSource && (!source.token.symbol || !matchedAsset?.logo)\n ? nativeCurrency?.symbol || source.token.symbol\n : source.token.symbol || nativeCurrency?.symbol || \"\";\n const sourceDecimals =\n isNativeSource && nativeCurrency?.decimals !== undefined\n ? nativeCurrency.decimals\n : source.token.decimals;\n const sourceLogo = resolveTokenLogo(source.token, source.chain.id);\n\n return {\n contractAddress: source.token.contractAddress,\n symbol: sourceSymbol,\n name: sourceSymbol,\n logo: sourceLogo ?? \"\",\n decimals: sourceDecimals,\n balance: matchedBreakdown?.balance\n ? `${matchedBreakdown.balance} ${sourceSymbol}`\n : `${source.amount} ${sourceSymbol}`,\n balanceInFiat:\n matchedBreakdown?.balanceInFiat != null\n ? `$${Number(matchedBreakdown.balanceInFiat).toFixed(2)}`\n : Number.isFinite(sourceValue)\n ? `$${sourceValue.toFixed(2)}`\n : \"$0.00\",\n chainId: source.chain.id,\n chainName: getShortChainName(\n source.chain.id,\n chainMeta?.name ?? source.chain.name\n ),\n chainLogo: chainMeta?.logo ?? source.chain.logo,\n userAmount: source.amount,\n userAmountUsd: Number.isFinite(sourceValue) ? source.value : undefined,\n userAmountMode: \"token\",\n };\n };\n\n const clearPendingSwapIntent = (\n clearQuote = true,\n options: { keepQuoteRefreshing?: boolean } = {}\n ) => {\n swapRunIdRef.current += 1;\n swapIntentRef.current?.deny();\n swapIntentRef.current = null;\n setIntentLoading(false);\n setTxError(null);\n if (!options.keepQuoteRefreshing) {\n setQuoteRefreshing(false);\n }\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setSwapQuoteIssue(null);\n resetProgressEvents();\n if (swapStepsListRef.current.length > 0 || steps.length > 0) {\n swapStepsListRef.current = [];\n resetSteps();\n } else {\n swapStepsListRef.current = [];\n }\n if (clearQuote) {\n setIntentToAmount(undefined);\n setIntentFeeUsd(undefined);\n setIntentData(null);\n if (!options.keepQuoteRefreshing) {\n setPredictiveQuote(null);\n }\n }\n };\n\n const clearSelectedSources = () => {\n setFromTokens((current) => (current.length === 0 ? current : []));\n setSourceSelectionTouched(false);\n setDepositSourceFilter(\"all\");\n setExactOutQuoteSourceModeValue(\"all\");\n };\n\n const resetExactOutSourcesToAuto = () => {\n setFromTokens((current) => (current.length === 0 ? current : []));\n setSourceSelectionTouched(false);\n setDepositSourceFilter(\"all\");\n setExactOutQuoteSourceModeValue(\"all\");\n setSourceSelectionRevision((current) => current + 1);\n };\n\n const getSourceAmountInput = (tokens: SwapTokenOption[]) => {\n const total = tokens.reduce(\n (sum, token) => sum + Number(token.userAmount || 0),\n 0\n );\n return total > 0 ? String(total) : \"\";\n };\n\n const minimumSourceUsd = new Decimal(1);\n const hasMinimumSourceUsdValue = (value: unknown) =>\n (parseFiatNumber(value) ?? new Decimal(0)).gte(minimumSourceUsd);\n const hasMinimumSourceUsdBalance = (\n token: Pick\n ) => hasMinimumSourceUsdValue(token.balanceInFiat);\n const filterMinimumSourceUsdTokens = (tokens: SwapTokenOption[]) =>\n tokens.filter(hasMinimumSourceUsdBalance);\n\n const getTokenUsdRateCacheKeyFromParts = (\n chainId?: number,\n contractAddress?: string,\n symbol?: string\n ) => {\n if (!chainId || !symbol) return \"\";\n return [\n chainId,\n (contractAddress || zeroAddress).toLowerCase(),\n symbol.toUpperCase(),\n ].join(\":\");\n };\n\n const getTokenUsdRateCacheKey = (\n token?: Pick\n ) =>\n getTokenUsdRateCacheKeyFromParts(\n token?.chainId,\n token?.contractAddress,\n token?.symbol\n );\n\n const getSymbolUsdRateCacheKey = (symbol?: string) =>\n symbol ? symbol.trim().toUpperCase() : \"\";\n\n const getCachedIntentUsdRate = (\n token?: Pick\n ) => {\n const tokenKey = getTokenUsdRateCacheKey(token);\n const cached = tokenKey\n ? intentDestinationUsdRateCacheRef.current[tokenKey]\n : undefined;\n const rate = parseFiatNumber(cached?.rate);\n return rate && rate.gt(0) ? rate : undefined;\n };\n\n const cacheDestinationUsdRateFromIntent = (\n intent?: SwapIntentData | null\n ) => {\n const destination = intent?.destination;\n const amount = parseFiatNumber(destination?.amount);\n const value = parseFiatNumber(destination?.value);\n const chainId = destination?.chain?.id;\n const symbol = destination?.token?.symbol;\n\n if (\n !amount ||\n !value ||\n amount.lte(0) ||\n value.lte(0) ||\n !chainId ||\n !symbol\n ) {\n return;\n }\n\n const rate = value.div(amount);\n if (!rate.isFinite() || rate.lte(0)) return;\n\n const cached: CachedIntentUsdRate = {\n amount: amount.toFixed(),\n rate: rate.toDecimalPlaces(18).toFixed(),\n updatedAt: Date.now(),\n value: value.toFixed(),\n };\n const tokenKey = getTokenUsdRateCacheKeyFromParts(\n chainId,\n destination?.token?.contractAddress,\n symbol\n );\n if (tokenKey) {\n intentDestinationUsdRateCacheRef.current[tokenKey] = cached;\n }\n\n const symbolKey = getSymbolUsdRateCacheKey(symbol);\n if (symbolKey) {\n intentSymbolUsdRateCacheRef.current[symbolKey] = cached;\n }\n };\n\n const getSwapBalanceTotalUsd = () =>\n (swapBalance ?? []).reduce((sum, asset) => {\n const breakdown = asset.breakdown ?? [];\n if (breakdown.length > 0) {\n return sum.plus(\n breakdown.reduce((breakdownSum, item) => {\n const value = parseFiatNumber(item.balanceInFiat) ?? new Decimal(0);\n return value.gte(minimumSourceUsd)\n ? breakdownSum.plus(value)\n : breakdownSum;\n }, new Decimal(0))\n );\n }\n\n const value = parseFiatNumber(asset.balanceInFiat) ?? new Decimal(0);\n return value.gte(minimumSourceUsd) ? sum.plus(value) : sum;\n }, new Decimal(0));\n\n const getTokenUsdRate = (token: SwapTokenOption) => {\n const tokenBalance = parseFiatNumber(token.balance) ?? new Decimal(0);\n const fiatBalance = parseFiatNumber(token.balanceInFiat) ?? new Decimal(0);\n if (tokenBalance.gt(0) && fiatBalance.gt(0)) {\n return fiatBalance.div(tokenBalance);\n }\n\n const priceUsd = parseFiatNumber(token.priceUSD);\n if (priceUsd && priceUsd.gt(0)) {\n return priceUsd;\n }\n\n const fallbackRate = getFiatValue(1, token.symbol);\n if (Number.isFinite(fallbackRate) && fallbackRate > 0) {\n return new Decimal(fallbackRate);\n }\n\n return getCachedIntentUsdRate(token) ?? new Decimal(0);\n };\n const getUsdRateForSymbol = (symbol?: string) => {\n if (!symbol) return new Decimal(0);\n const fiat = getFiatValue(1, symbol);\n if (Number.isFinite(fiat) && fiat > 0) {\n return new Decimal(fiat);\n }\n\n const cached =\n intentSymbolUsdRateCacheRef.current[getSymbolUsdRateCacheKey(symbol)];\n const rate = parseFiatNumber(cached?.rate);\n return rate && rate.gt(0) ? rate : new Decimal(0);\n };\n\n const getFeeTokenLookupAddress = (value?: string | null) => {\n const lower = (value ?? \"\").toLowerCase();\n if (!lower || lower === \"0x\" || isNativeTokenAddress(lower)) {\n return zeroAddress;\n }\n return lower;\n };\n\n const getTokenUsdRateFromBalances = (\n chainId?: number,\n contractAddress?: string,\n symbol?: string\n ) => {\n if (!chainId) return undefined;\n const lookupAddress = getFeeTokenLookupAddress(contractAddress);\n const lookupSymbol = symbol?.toUpperCase();\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n if (breakdown.chain?.id !== chainId) continue;\n const breakdownAddress = getFeeTokenLookupAddress(\n breakdown.contractAddress\n );\n const addressMatches =\n lookupAddress && breakdownAddress === lookupAddress;\n const symbolMatches =\n lookupSymbol &&\n [breakdown.symbol, asset.symbol]\n .filter(Boolean)\n .some((candidate) => candidate.toUpperCase() === lookupSymbol);\n if (!addressMatches && !symbolMatches) continue;\n\n const balance = parseFiatNumber(breakdown.balance);\n const fiatBalance = parseFiatNumber(breakdown.balanceInFiat);\n if (balance && fiatBalance && balance.gt(0) && fiatBalance.gt(0)) {\n return fiatBalance.div(balance);\n }\n }\n }\n\n return undefined;\n };\n\n const getTokenUsdRateFromSupportedChains = (\n chains: any[] | null | undefined,\n chainId?: number,\n contractAddress?: string,\n symbol?: string\n ) => {\n if (!chainId) return undefined;\n const chain = chains?.find(\n (item: any) => Number(item?.id ?? item?.chainId) === chainId\n );\n const tokens = chain?.tokens ?? chain?.assets ?? [];\n const lookupAddress = getFeeTokenLookupAddress(contractAddress);\n const lookupSymbol = symbol?.toUpperCase();\n const matchedToken = tokens.find((token: any) => {\n const tokenAddress = getFeeTokenLookupAddress(\n token?.contractAddress ?? token?.address ?? token?.tokenAddress\n );\n const addressMatches = lookupAddress && tokenAddress === lookupAddress;\n const tokenSymbol = (token?.symbol ?? token?.tokenSymbol ?? \"\")\n .toString()\n .toUpperCase();\n const symbolMatches = lookupSymbol && tokenSymbol === lookupSymbol;\n return addressMatches || symbolMatches;\n });\n const priceUsd = parseFiatNumber(\n matchedToken?.priceUSD ??\n matchedToken?.priceUsd ??\n matchedToken?.usdPrice ??\n matchedToken?.price\n );\n return priceUsd && priceUsd.gt(0) ? priceUsd : undefined;\n };\n\n const getIntentDestinationGasUsdValue = (\n intent?: SwapIntentData | null\n ) => {\n const gas = intent?.destination?.gas;\n const explicitValue = parseFiatNumber(gas?.value);\n if (explicitValue && explicitValue.gt(0)) return explicitValue;\n\n const amount = parseFiatNumber(gas?.amount);\n if (!amount || amount.lte(0)) return undefined;\n\n const chainId = intent?.destination?.chain?.id;\n const contractAddress = gas?.token?.contractAddress;\n const symbol = gas?.token?.symbol;\n const rate =\n getTokenUsdRateFromBalances(chainId, contractAddress, symbol) ??\n getTokenUsdRateFromSupportedChains(\n swapSupportedChainsAndTokens,\n chainId,\n contractAddress,\n symbol\n ) ??\n getTokenUsdRateFromSupportedChains(\n supportedChainsAndTokens,\n chainId,\n contractAddress,\n symbol\n ) ??\n getUsdRateForSymbol(symbol);\n\n return rate.gt(0) ? amount.mul(rate) : undefined;\n };\n\n const getCachedDestinationUsdRate = (token?: SwapTokenOption) => {\n return getCachedIntentUsdRate(token);\n };\n\n const resolveUsdRateForSymbol = async (symbol?: string) => {\n if (!symbol) return new Decimal(0);\n\n const localRate = getUsdRateForSymbol(symbol);\n if (localRate.gt(0)) return localRate;\n\n try {\n const resolvedRate = await resolveTokenUsdRate(symbol);\n return resolvedRate && resolvedRate > 0\n ? new Decimal(resolvedRate)\n : new Decimal(0);\n } catch {\n return new Decimal(0);\n }\n };\n\n const getTokenUsdValue = (\n token: SwapTokenOption,\n fallbackAmount?: string\n ) => {\n const amountNumber =\n parseFiatNumber(token.userAmount || fallbackAmount) ?? new Decimal(0);\n if (amountNumber.lte(0)) return new Decimal(0);\n const quotedUsd = parseFiatNumber(token.userAmountUsd);\n if (quotedUsd && quotedUsd.gte(0)) return quotedUsd;\n if (token.userAmountMode === \"usd\") return amountNumber;\n\n const rate = getTokenUsdRate(token);\n return rate.gt(0) ? amountNumber.mul(rate) : new Decimal(0);\n };\n\n const getTokenBalanceAmount = (token: SwapTokenOption) =>\n parseFiatNumber(token.balance) ?? new Decimal(0);\n\n const getTokenBalanceUsd = (token: SwapTokenOption) =>\n parseFiatNumber(token.balanceInFiat) ?? new Decimal(0);\n\n const getSdkExactOutSourcePriority = (token: SwapTokenOption) => {\n const isSameChain =\n Boolean(token.chainId && toToken?.chainId) &&\n token.chainId === toToken?.chainId;\n const isSameToken =\n Boolean(token.contractAddress && toToken?.contractAddress) &&\n ((isNativeTokenAddress(token.contractAddress) &&\n isNativeTokenAddress(toToken?.contractAddress)) ||\n token.contractAddress.toLowerCase() ===\n toToken?.contractAddress.toLowerCase());\n const isStable = isSdkExactOutStableSymbol(token.symbol);\n const isGas = isNativeTokenAddress(token.contractAddress);\n const isEthereum = token.chainId === ETHEREUM_MAINNET_CHAIN_ID;\n\n if (isSameChain) {\n if (isSameToken) return 1;\n if (isStable) return 2;\n if (isGas) return 3;\n return 4;\n }\n\n if (isEthereum) {\n if (isSameToken) return 8;\n if (isStable) return 9;\n if (isGas) return 10;\n return 11;\n }\n\n if (isSameToken) return 5;\n if (isStable) return 6;\n return 7;\n };\n\n const sortExactOutSourcesBySdkPriority = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const priorityDiff =\n getSdkExactOutSourcePriority(a) - getSdkExactOutSourcePriority(b);\n if (priorityDiff !== 0) return priorityDiff;\n\n const usdDiff = getTokenBalanceUsd(b).cmp(getTokenBalanceUsd(a));\n if (usdDiff !== 0) return usdDiff;\n\n return `${a.symbol} ${a.chainName ?? \"\"}`.localeCompare(\n `${b.symbol} ${b.chainName ?? \"\"}`\n );\n });\n\n const getTokenAmountForUsd = (token: SwapTokenOption, usdAmount: Decimal) => {\n const rate = getTokenUsdRate(token);\n if (rate.lte(0) || usdAmount.lte(0)) return new Decimal(0);\n return usdAmount.div(rate);\n };\n\n const getUsdForTokenAmount = (\n token: SwapTokenOption,\n tokenAmount: Decimal\n ) => {\n const rate = getTokenUsdRate(token);\n if (rate.lte(0) || tokenAmount.lte(0)) return new Decimal(0);\n return tokenAmount.mul(rate);\n };\n\n const getExactOutDestinationBalanceCoverage = ({\n requestedAmount,\n requestedUsd,\n producedAmount,\n producedUsd,\n token = toToken,\n }: {\n requestedAmount?: Decimal;\n requestedUsd?: Decimal;\n producedAmount?: Decimal;\n producedUsd?: Decimal;\n token?: SwapTokenOption;\n }) => {\n if (\n (activeMode !== \"deposit\" && activeMode !== \"send\") ||\n !token ||\n !requestedAmount ||\n requestedAmount.lte(0)\n ) {\n return null;\n }\n\n const balanceAmount =\n parseFiatNumber(destinationBalance) ??\n parseFiatNumber(token.balance) ??\n new Decimal(0);\n if (balanceAmount.lte(0)) return null;\n\n const externalAmount =\n producedAmount && producedAmount.gt(0) ? producedAmount : new Decimal(0);\n const uncoveredAmount = Decimal.max(\n requestedAmount.minus(externalAmount),\n new Decimal(0)\n );\n const coveredAmount = Decimal.min(balanceAmount, uncoveredAmount);\n if (coveredAmount.lte(0)) return null;\n\n const requestedRate =\n requestedUsd && requestedUsd.gt(0)\n ? requestedUsd.div(requestedAmount)\n : undefined;\n const producedRate =\n producedUsd && producedUsd.gt(0) && producedAmount && producedAmount.gt(0)\n ? producedUsd.div(producedAmount)\n : undefined;\n const fallbackRate = getTokenUsdRate(token);\n const usdRate =\n requestedRate && requestedRate.gt(0)\n ? requestedRate\n : producedRate && producedRate.gt(0)\n ? producedRate\n : fallbackRate.gt(0)\n ? fallbackRate\n : undefined;\n\n return {\n amount: coveredAmount,\n usd: usdRate ? coveredAmount.mul(usdRate) : undefined,\n };\n };\n\n const buildDestinationBalanceDisplayToken = (\n coverage: ReturnType,\n token?: SwapTokenOption\n ): SwapTokenOption | null => {\n if (!coverage || !token || coverage.amount.lte(0)) return null;\n\n const amount = coverage.amount\n .toDecimalPlaces(Math.max(0, token.decimals ?? 18), Decimal.ROUND_DOWN)\n .toFixed();\n const usd = coverage.usd?.toDecimalPlaces(6, Decimal.ROUND_DOWN).toFixed();\n const balanceUsd = coverage.usd\n ? `$${coverage.usd.toDecimalPlaces(2, Decimal.ROUND_DOWN).toFixed()}`\n : token.balanceInFiat || \"$0.00\";\n\n return {\n ...token,\n balance: amount,\n balanceInFiat: balanceUsd,\n userAmount: amount,\n userAmountMode: \"token\",\n userAmountUsd: usd,\n };\n };\n\n const cacheSymbolUsdRate = (symbol: string | undefined, rate: Decimal) => {\n const symbolKey = getSymbolUsdRateCacheKey(symbol);\n if (!symbolKey || rate.lte(0)) return;\n\n intentSymbolUsdRateCacheRef.current[symbolKey] = {\n amount: \"1\",\n rate: rate.toDecimalPlaces(18).toFixed(),\n updatedAt: Date.now(),\n value: rate.toFixed(),\n };\n };\n\n const getPredictiveDestinationKey = (token?: SwapTokenOption) => {\n const tokenKey = getTokenUsdRateCacheKey(token);\n return tokenKey ? `destination:${tokenKey}` : \"\";\n };\n\n const getPredictiveSourceKey = (token: SwapTokenOption) =>\n [\n token.chainId ?? \"unknown\",\n (token.contractAddress || zeroAddress).toLowerCase(),\n token.symbol.toUpperCase(),\n ].join(\":\");\n\n const getPredictiveQuoteCacheKey = (\n mode = activeMode,\n type = swapType,\n destination = toToken,\n sources = fromTokens\n ) => {\n const destinationKey = getPredictiveDestinationKey(destination);\n if (!destinationKey) return \"\";\n if (mode !== \"swap\" || type !== \"exactIn\") {\n return `exactOut:${destinationKey}`;\n }\n\n const sourceKey = getExpandedSourceTokens(sources)\n .map(getPredictiveSourceKey)\n .sort()\n .join(\"+\");\n return sourceKey ? `exactIn:${sourceKey}->${destinationKey}` : \"\";\n };\n\n const getPredictiveDisplayAmount = (\n amount: Decimal,\n token?: Pick\n ) => {\n const decimals = Math.min(\n PREDICTIVE_QUOTE_DISPLAY_DECIMALS,\n Math.max(0, token?.decimals ?? 18)\n );\n return amount.toDecimalPlaces(decimals, Decimal.ROUND_DOWN).toFixed();\n };\n\n const resolveUsdRateForToken = async (token?: SwapTokenOption) => {\n if (!token?.symbol) return new Decimal(0);\n\n const localRate = getTokenUsdRate(token);\n if (localRate.gt(0)) return localRate;\n\n const resolvedRate = await resolveUsdRateForSymbol(token.symbol);\n if (resolvedRate.gt(0)) {\n cacheSymbolUsdRate(token.symbol, resolvedRate);\n }\n return resolvedRate;\n };\n\n const getDestinationReceiveLimitUsd = (token?: SwapTokenOption) => {\n if (!token?.chainId) return undefined;\n const limit = DESTINATION_RECEIVE_LIMIT_USD_BY_CHAIN_ID[token.chainId];\n return limit ? new Decimal(limit) : undefined;\n };\n\n const getImmediateDestinationReceiveUsdRate = (token?: SwapTokenOption) => {\n const priceUsd = parseFiatNumber(token?.priceUSD);\n if (priceUsd && priceUsd.gt(0)) return priceUsd;\n\n const cachedRate = getCachedDestinationUsdRate(token);\n if (cachedRate && cachedRate.gt(0)) return cachedRate;\n\n if (!token) return undefined;\n const localRate = getTokenUsdRate(token);\n return localRate.gt(0) ? localRate : undefined;\n };\n\n const getExactInSourceUsdForReceiveLimit = (\n sourceTokens: SwapTokenOption[],\n inputAmount: string\n ) => {\n if (sourceTokens.length === 0) return undefined;\n let hasPositiveSourceAmount = false;\n let totalUsd = new Decimal(0);\n\n for (const token of sourceTokens) {\n const fallbackAmount =\n sourceTokens.length === 1 ? inputAmount : undefined;\n const sourceAmount = parseFiatNumber(token.userAmount || fallbackAmount);\n if (!sourceAmount || sourceAmount.lte(0)) continue;\n\n hasPositiveSourceAmount = true;\n const sourceUsd = getTokenUsdValue(token, fallbackAmount);\n if (sourceUsd.lte(0)) return undefined;\n totalUsd = totalUsd.plus(sourceUsd);\n }\n\n return hasPositiveSourceAmount ? totalUsd : undefined;\n };\n\n const buildReceiveAmountIssue = ({\n destinationRate,\n destinationToken = toToken,\n inputAmount = amount,\n mode = activeMode,\n sourceTokens = fromTokens,\n type = swapType,\n }: {\n destinationRate?: Decimal;\n destinationToken?: SwapTokenOption;\n inputAmount?: string;\n mode?: NexusWidgetMode;\n sourceTokens?: SwapTokenOption[];\n type?: SwapType;\n } = {}): ReceiveAmountIssue | null => {\n const limit = getDestinationReceiveLimitUsd(destinationToken);\n if (!limit || !destinationToken) return null;\n\n const parsedAmount = parseFiatNumber(inputAmount);\n if (!parsedAmount || parsedAmount.lte(0)) return null;\n if (mode === \"swap\" && type === \"exactIn\" && sourceTokens.length === 0) {\n return null;\n }\n\n const chainName = getShortChainName(\n destinationToken.chainId,\n destinationToken.chainName\n );\n const resolvedDestinationRate =\n destinationRate ??\n getImmediateDestinationReceiveUsdRate(destinationToken);\n\n if (!resolvedDestinationRate || resolvedDestinationRate.lte(0)) {\n return {\n ctaLabel: \"Price unavailable\",\n message: `Unable to price ${destinationToken.symbol} on ${chainName}. Select another receive token.`,\n type: \"unpricedReceiveToken\",\n };\n }\n\n let receiveUsd: Decimal | undefined;\n if (mode === \"swap\" && type === \"exactIn\") {\n receiveUsd = getExactInSourceUsdForReceiveLimit(\n sourceTokens,\n inputAmount\n );\n if (!receiveUsd || receiveUsd.lte(0)) {\n return {\n ctaLabel: \"Price unavailable\",\n message: `Unable to price selected assets for ${chainName}'s receive limit.`,\n type: \"unpricedReceiveToken\",\n };\n }\n } else if (mode === \"deposit\" && depositAmountMode === \"usd\") {\n receiveUsd = parsedAmount;\n } else {\n receiveUsd = parsedAmount.mul(resolvedDestinationRate);\n }\n\n if (receiveUsd.gt(limit)) {\n return {\n ctaLabel: \"Receive limit exceeded\",\n message: `Maximum receive amount on ${chainName} is ${formatUsdDisplay(limit)}.`,\n type: \"receiveLimitExceeded\",\n };\n }\n\n return null;\n };\n\n const buildConfiguredAmountIssue = (\n inputAmount = amount\n ): ReceiveAmountIssue | null => {\n if (!amountInputConfig || !inputAmount) return null;\n const parsedAmount = parseFiatNumber(inputAmount);\n if (!parsedAmount || parsedAmount.lte(0)) return null;\n const tokenSuffix = toToken?.symbol?.trim()\n ? ` ${toToken.symbol.trim()}`\n : \"\";\n\n const minAmount = parseFiatNumber(amountInputConfig.min);\n if (minAmount && parsedAmount.lt(minAmount)) {\n return {\n ctaLabel: \"Below minimum\",\n message: `Minimum deposit amount is ${minAmount.toFixed()}${tokenSuffix}.`,\n type: \"configuredAmountLimit\",\n };\n }\n\n const maxAmount = parseFiatNumber(amountInputConfig.max);\n if (maxAmount && parsedAmount.gt(maxAmount)) {\n return {\n ctaLabel: \"Above maximum\",\n message: `Maximum deposit amount is ${maxAmount.toFixed()}${tokenSuffix}.`,\n type: \"configuredAmountLimit\",\n };\n }\n\n return null;\n };\n\n const clearPreviewForBlockingAmountIssue = () => {\n clearPendingSwapIntent(true);\n setQuoteRefreshing(false);\n setIntentLoading(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setTxError(null);\n setSwapQuoteIssue(null);\n };\n\n const applyReceiveAmountIssue = (issue: ReceiveAmountIssue | null) => {\n const key = issue ? `${issue.type}:${issue.message}` : \"\";\n receiveAmountIssueRef.current = issue;\n if (receiveAmountIssueKeyRef.current !== key) {\n receiveAmountIssueKeyRef.current = key;\n setReceiveAmountIssue(issue);\n }\n if (!issue) return;\n\n clearPendingSwapIntent(true);\n setQuoteRefreshing(false);\n setIntentLoading(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setTxError(null);\n };\n\n const getPredictiveExactInSourceTokens = () => {\n const expanded = getExpandedSourceTokens(fromTokens);\n if (expanded.length === 0) return [];\n\n return expanded\n .map((token) => {\n const userAmount =\n token.userAmount ||\n (expanded.length === 1 && hasPositiveDecimalInput(amount)\n ? amount\n : \"\");\n return { ...token, userAmount };\n })\n .filter((token) => hasPositiveDecimalInput(token.userAmount));\n };\n\n const sortUnifiedSourceTokens = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const fiatDiff = getTokenBalanceUsd(b).cmp(getTokenBalanceUsd(a));\n if (fiatDiff !== 0) return fiatDiff;\n return getTokenBalanceAmount(b).cmp(getTokenBalanceAmount(a));\n });\n\n const allocateUnifiedExactInToken = (\n token: SwapTokenOption,\n fallbackAmount?: string\n ) => {\n if (!token.isUnified || !token.sourceTokens?.length) return [token];\n\n const rawAmount =\n parseFiatNumber(token.userAmount || fallbackAmount) ?? new Decimal(0);\n if (rawAmount.lte(0)) return [];\n\n const sortedSources = sortUnifiedSourceTokens(token.sourceTokens).filter(\n (source) =>\n source.chainId &&\n source.contractAddress &&\n getTokenBalanceAmount(source).gt(0) &&\n hasMinimumSourceUsdBalance(source)\n );\n const allocated: SwapTokenOption[] = [];\n\n if (token.userAmountMode === \"usd\") {\n let remainingUsd = rawAmount;\n\n for (const source of sortedSources) {\n if (remainingUsd.lte(0)) break;\n\n const availableUsd = getTokenBalanceUsd(source);\n if (availableUsd.lte(0)) continue;\n\n const targetUsd = Decimal.min(remainingUsd, availableUsd);\n const tokenAmount = getTokenAmountForUsd(\n source,\n targetUsd\n ).toDecimalPlaces(\n Math.max(0, source.decimals || 18),\n Decimal.ROUND_DOWN\n );\n if (tokenAmount.lte(0)) continue;\n\n const actualUsd = getUsdForTokenAmount(source, tokenAmount);\n allocated.push({\n ...source,\n userAmount: tokenAmount.toFixed(),\n userAmountMode: \"token\",\n userAmountUsd: actualUsd\n .toDecimalPlaces(6, Decimal.ROUND_DOWN)\n .toFixed(),\n });\n remainingUsd = remainingUsd.minus(targetUsd);\n }\n\n return allocated;\n }\n\n let remainingTokenAmount = rawAmount;\n\n for (const source of sortedSources) {\n if (remainingTokenAmount.lte(0)) break;\n\n const availableTokenAmount = getTokenBalanceAmount(source);\n if (availableTokenAmount.lte(0)) continue;\n\n const tokenAmount = Decimal.min(\n remainingTokenAmount,\n availableTokenAmount\n ).toDecimalPlaces(Math.max(0, source.decimals || 18), Decimal.ROUND_DOWN);\n if (tokenAmount.lte(0)) continue;\n\n const actualUsd = getUsdForTokenAmount(source, tokenAmount);\n allocated.push({\n ...source,\n userAmount: tokenAmount.toFixed(),\n userAmountMode: \"token\",\n userAmountUsd: actualUsd\n .toDecimalPlaces(6, Decimal.ROUND_DOWN)\n .toFixed(),\n });\n remainingTokenAmount = remainingTokenAmount.minus(tokenAmount);\n }\n\n return allocated;\n };\n\n const getExactInSourceTokens = (\n tokens: SwapTokenOption[],\n fallbackAmount?: string\n ) =>\n tokens\n .flatMap((token) =>\n token.isUnified\n ? allocateUnifiedExactInToken(token, fallbackAmount)\n : [token]\n )\n .filter(hasMinimumSourceUsdBalance);\n\n const hasPositiveDecimalInput = (value: unknown) =>\n Boolean(parseFiatNumber(value)?.gt(0));\n\n const hasPositiveSourceSpend = (token: SwapTokenOption) =>\n hasPositiveDecimalInput(token.userAmount) ||\n hasPositiveDecimalInput(token.userAmountUsd);\n\n const getReadyExactInSourceTokens = (tokens: SwapTokenOption[]) =>\n getExactInSourceTokens(tokens).filter(\n (token) =>\n Boolean(token.chainId && token.contractAddress) &&\n hasPositiveDecimalInput(token.userAmount)\n );\n\n const hasReadyExactInSwapInput = (\n tokens: SwapTokenOption[],\n destination?: SwapTokenOption\n ) =>\n Boolean(\n destination?.chainId &&\n destination.contractAddress &&\n getReadyExactInSourceTokens(tokens).length > 0\n );\n\n const getExpandedSourceTokens = (tokens: SwapTokenOption[]) => {\n const expanded = tokens.flatMap((token) =>\n token.isUnified && token.sourceTokens?.length\n ? token.sourceTokens\n : [token]\n );\n const seen = new Set();\n return expanded.filter((token) => {\n if (!token.chainId || !token.contractAddress) return false;\n if (\n !isSwapSupportedBySdkChainList(\n token.chainId,\n swapSupportedChainsAndTokens\n )\n ) {\n return false;\n }\n const key = `${token.chainId}-${token.contractAddress.toLowerCase()}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n };\n\n const getNativeGasBalanceForChain = (chainId: number) => {\n const nativeSymbol =\n CHAIN_METADATA[chainId]?.nativeCurrency?.symbol?.toUpperCase();\n let balance = new Decimal(0);\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n if (breakdown.chain?.id !== chainId) continue;\n const breakdownSymbol = (\n breakdown.symbol ??\n asset.symbol ??\n \"\"\n ).toUpperCase();\n const assetSymbol = (asset.symbol ?? \"\").toUpperCase();\n const isNativeBalance =\n isNativeTokenAddress(breakdown.contractAddress) ||\n Boolean(\n nativeSymbol &&\n (breakdownSymbol === nativeSymbol || assetSymbol === nativeSymbol)\n );\n\n if (!isNativeBalance) continue;\n balance = balance.plus(\n parseFiatNumber(breakdown.balance) ?? new Decimal(0)\n );\n }\n }\n\n return balance;\n };\n\n const hasGasForSource = (token: SwapTokenOption) => {\n if (!token.chainId || !token.contractAddress) return false;\n const tokenBalance = parseFiatNumber(token.balance) ?? new Decimal(0);\n if (tokenBalance.lte(0)) return false;\n if (isNativeTokenAddress(token.contractAddress)) return true;\n return getNativeGasBalanceForChain(token.chainId).gt(0);\n };\n\n const getGasCapableBalanceSourceTokens = () => {\n const tokens: SwapTokenOption[] = [];\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n const chainId = breakdown.chain?.id;\n const contractAddress = breakdown.contractAddress;\n const balance = parseFiatNumber(breakdown.balance) ?? new Decimal(0);\n const fiatBalance = parseFiatNumber(breakdown.balanceInFiat);\n if (\n !chainId ||\n !contractAddress ||\n balance.lte(0) ||\n !fiatBalance ||\n fiatBalance.lt(minimumSourceUsd)\n )\n continue;\n\n const chainMeta = CHAIN_METADATA[chainId];\n const symbol = breakdown.symbol ?? asset.symbol;\n tokens.push({\n chainId,\n chainLogo: chainMeta?.logo ?? breakdown.chain?.logo,\n chainName: getShortChainName(\n chainId,\n chainMeta?.name ?? breakdown.chain?.name\n ),\n contractAddress,\n decimals: breakdown.decimals ?? asset.decimals ?? 18,\n logo: asset.logo ?? \"\",\n name: symbol,\n symbol,\n balance: breakdown.balance,\n balanceInFiat:\n fiatBalance !== undefined\n ? `$${fiatBalance.toDecimalPlaces(2).toFixed()}`\n : \"$0.00\",\n });\n }\n }\n\n return getExpandedSourceTokens(tokens).filter(hasGasForSource);\n };\n\n const getMinimumBalanceSourceTokens = () =>\n filterMinimumSourceUsdTokens(\n getExpandedSourceTokens(\n swapBalance\n ? deriveTokenOptions(swapBalance, swapSupportedChainsAndTokens)\n : []\n )\n );\n const getHeldDestinationTokenOption = () => {\n if (!toToken?.chainId || !toToken.contractAddress) return undefined;\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n const chainId = breakdown.chain?.id;\n if (chainId !== toToken.chainId) continue;\n\n const breakdownAddress = breakdown.contractAddress;\n const addressMatches =\n breakdownAddress &&\n (breakdownAddress.toLowerCase() ===\n toToken.contractAddress.toLowerCase() ||\n (isNativeTokenAddress(breakdownAddress) &&\n isNativeTokenAddress(toToken.contractAddress)));\n const symbolMatches =\n (breakdown.symbol ?? asset.symbol ?? \"\").toUpperCase() ===\n toToken.symbol.toUpperCase();\n\n if (!addressMatches && !symbolMatches) continue;\n\n const balanceAmount = parseFiatNumber(breakdown.balance);\n if (!balanceAmount || balanceAmount.lte(0)) continue;\n\n const chainMeta = CHAIN_METADATA[chainId];\n const symbol = breakdown.symbol ?? asset.symbol ?? toToken.symbol;\n const fiatBalance = parseFiatNumber(breakdown.balanceInFiat);\n\n return {\n chainId,\n chainLogo:\n chainMeta?.logo ?? breakdown.chain?.logo ?? toToken.chainLogo,\n chainName: getShortChainName(\n chainId,\n chainMeta?.name ?? breakdown.chain?.name ?? toToken.chainName\n ),\n contractAddress: breakdown.contractAddress ?? toToken.contractAddress,\n decimals:\n breakdown.decimals ?? asset.decimals ?? toToken.decimals ?? 18,\n logo: asset.logo ?? toToken.logo,\n name: symbol,\n symbol,\n balance: breakdown.balance,\n balanceInFiat:\n fiatBalance !== undefined\n ? `$${fiatBalance.toDecimalPlaces(2).toFixed()}`\n : \"$0.00\",\n } satisfies SwapTokenOption;\n }\n }\n\n return undefined;\n };\n\n const getDepositDestinationForSourceSelection = () => {\n const destination =\n activeMode === \"deposit\" ? selectedOpportunity : toToken;\n const chainId = destination?.chainId;\n const tokenAddress =\n activeMode === \"deposit\"\n ? selectedOpportunity?.tokenAddress\n : toToken?.contractAddress;\n const tokenSymbol =\n activeMode === \"deposit\"\n ? selectedOpportunity?.tokenSymbol\n : toToken?.symbol;\n\n if (!chainId || !tokenAddress || !tokenSymbol) return undefined;\n\n return {\n chainId,\n tokenAddress: tokenAddress as `0x${string}`,\n tokenSymbol,\n };\n };\n const getDestinationSourceIdForDeposit = () => {\n const destination = getDepositDestinationForSourceSelection();\n return destination\n ? getDepositSourceId(destination.tokenAddress, destination.chainId)\n : undefined;\n };\n const getDepositSourceTargetUsd = () => {\n if (activeMode !== \"deposit\") return undefined;\n const requestedUsd = depositUsdDecimal;\n if (!requestedUsd || requestedUsd.lte(0)) return undefined;\n\n const coverage = getExactOutDestinationBalanceCoverage({\n requestedAmount: depositTokenAmountForQuote,\n requestedUsd,\n token: toToken,\n });\n return Decimal.max(\n requestedUsd.minus(coverage?.usd ?? new Decimal(0)),\n new Decimal(0)\n );\n };\n\n const getDepositSourceIdsFromTokens = (tokens: SwapTokenOption[]) =>\n getExpandedSourceTokens(tokens)\n .filter((token) => token.chainId && token.contractAddress)\n .map((token) =>\n getDepositSourceId(token.contractAddress, token.chainId!)\n );\n\n const getDepositTokenOptionsBySourceId = () => {\n const map = new Map();\n const sourceTokens = [\n ...(swapBalance\n ? deriveTokenOptions(swapBalance, swapSupportedChainsAndTokens)\n : []),\n ...fromTokens,\n ];\n\n for (const token of getExpandedSourceTokens(sourceTokens)) {\n if (!token.chainId || !token.contractAddress) continue;\n const id = getDepositSourceId(token.contractAddress, token.chainId);\n if (!map.has(id)) {\n map.set(id, {\n ...token,\n userAmount: \"\",\n });\n }\n }\n\n return map;\n };\n\n const getDepositSourceTokensForIds = (sourceIds: string[]) => {\n const tokenBySourceId = getDepositTokenOptionsBySourceId();\n return sourceIds\n .map((sourceId) => tokenBySourceId.get(sourceId))\n .filter((token): token is SwapTokenOption => Boolean(token))\n .map((token) => ({ ...token, userAmount: \"\" }));\n };\n\n const getResolvedDepositSourceSelection = (options?: {\n filter?: DepositSourceFilter;\n selectedTokens?: SwapTokenOption[];\n isManualSelection?: boolean;\n targetAmountUsd?: Decimal;\n }) => {\n const destination = getDepositDestinationForSourceSelection();\n if (!destination) {\n return { sourcePoolIds: [], selectedSourceIds: [], fromSources: [] };\n }\n\n const manualSelection =\n options?.isManualSelection ?? sourceSelectionTouched;\n const selectedTokensForResolution = options?.selectedTokens ?? fromTokens;\n const selectedSourceIds = getDepositSourceIdsFromTokens(\n selectedTokensForResolution\n );\n const destinationSourceId = getDestinationSourceIdForDeposit();\n const targetAmountUsd =\n options?.targetAmountUsd ??\n (activeMode === \"deposit\"\n ? getDepositSourceTargetUsd()\n : activeMode === \"send\"\n ? new Decimal(sendAmountUsd || 0)\n : undefined);\n\n return resolveDepositSourceSelection({\n swapBalance,\n destination,\n filter: manualSelection\n ? \"custom\"\n : (options?.filter ?? depositSourceFilter),\n selectedSourceIds,\n isManualSelection: manualSelection,\n minimumBalanceUsd: minimumSourceUsd.toNumber(),\n targetAmountUsd: targetAmountUsd?.toNumber(),\n excludedSourceIds: destinationSourceId ? [destinationSourceId] : [],\n });\n };\n\n const getExactOutSourceTokens = (\n mode: \"all\" | \"selected\" = exactOutQuoteSourceModeRef.current,\n targetAmountUsd?: Decimal\n ) => {\n if (activeMode === \"deposit\") {\n const selection = getResolvedDepositSourceSelection({ targetAmountUsd });\n return getDepositSourceTokensForIds(\n mode === \"all\" ? selection.sourcePoolIds : selection.selectedSourceIds\n );\n }\n\n if (activeMode === \"send\" && mode === \"selected\" && fromTokens.length > 0) {\n return filterMinimumSourceUsdTokens(\n getExpandedSourceTokens(fromTokens)\n ).filter(hasGasForSource);\n }\n\n return getGasCapableBalanceSourceTokens();\n };\n\n const buildExplicitSourcesPayload = (tokens: SwapTokenOption[]) => {\n const eligibleTokens = filterMinimumSourceUsdTokens(tokens).filter(\n (token) => token.chainId && token.contractAddress\n );\n return {\n sources: eligibleTokens.map((token) => ({\n chainId: token.chainId!,\n tokenAddress: token.contractAddress as `0x${string}`,\n })),\n };\n };\n\n const getSdkSourceKey = (source: {\n chainId: number;\n tokenAddress: `0x${string}`;\n }) => {\n const normalizedAddress = isNativeTokenAddress(source.tokenAddress)\n ? zeroAddress\n : source.tokenAddress.toLowerCase();\n return `${source.chainId}:${normalizedAddress}`;\n };\n\n const dedupeSdkSources = (\n sources: Array<\n | {\n chainId: number;\n tokenAddress: `0x${string}`;\n }\n | undefined\n >\n ) => {\n const seen = new Set();\n return sources.filter(\n (\n source\n ): source is {\n chainId: number;\n tokenAddress: `0x${string}`;\n } => {\n if (!source) return false;\n const key = getSdkSourceKey(source);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n }\n );\n };\n\n const getHeldDestinationTokenSource = () => {\n const heldDestinationToken = getHeldDestinationTokenOption();\n if (\n !heldDestinationToken?.chainId ||\n !heldDestinationToken.contractAddress\n ) {\n return undefined;\n }\n\n return {\n chainId: heldDestinationToken.chainId,\n tokenAddress: heldDestinationToken.contractAddress as `0x${string}`,\n };\n };\n\n const shouldSendExactOutSourceAllowlist = () => {\n if (activeMode === \"deposit\") {\n return sourceSelectionTouched || depositSourceFilter !== \"all\";\n }\n\n if (activeMode === \"send\") {\n return exactOutQuoteSourceModeRef.current === \"selected\";\n }\n\n return true;\n };\n\n const buildExactOutSourcesPayload = (tokens: SwapTokenOption[]) => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") {\n return buildExplicitSourcesPayload(tokens);\n }\n\n const sourceTokens = shouldSendExactOutSourceAllowlist()\n ? tokens\n : getExactOutSourceTokens(\"all\");\n const explicitSources = buildExplicitSourcesPayload(sourceTokens).sources;\n const sources = dedupeSdkSources([\n ...explicitSources,\n getHeldDestinationTokenSource(),\n ]);\n\n return sources.length > 0 ? { sources } : {};\n };\n\n const buildPredictiveExactOutSources = async (requiredSourceUsd: Decimal) => {\n if (requiredSourceUsd.lte(0)) return [];\n\n const destinationKey = getTokenSelectionKey(toToken);\n const candidates = sortExactOutSourcesBySdkPriority(\n getExactOutSourceTokens(\n exactOutQuoteSourceModeRef.current,\n requiredSourceUsd\n )\n .filter((token) => getTokenSelectionKey(token) !== destinationKey)\n .filter(hasMinimumSourceUsdBalance)\n );\n const sources: SwapTokenOption[] = [];\n let remainingUsd = requiredSourceUsd;\n\n for (const token of candidates) {\n if (remainingUsd.lte(0)) break;\n\n const availableUsd = getTokenBalanceUsd(token);\n if (availableUsd.lt(minimumSourceUsd)) continue;\n\n const rate = await resolveUsdRateForToken(token);\n if (rate.lte(0)) continue;\n\n const targetUsd = Decimal.min(remainingUsd, availableUsd);\n const tokenAmount = targetUsd\n .div(rate)\n .toDecimalPlaces(Math.max(0, token.decimals || 18), Decimal.ROUND_DOWN);\n if (tokenAmount.lte(0)) continue;\n\n sources.push({\n ...token,\n userAmount: tokenAmount.toFixed(),\n userAmountMode: \"token\",\n userAmountUsd: targetUsd\n .toDecimalPlaces(6, Decimal.ROUND_DOWN)\n .toFixed(),\n });\n remainingUsd = remainingUsd.minus(targetUsd);\n }\n\n return remainingUsd.gt(0.01) ? [] : sources;\n };\n\n const getErrorText = (error: unknown) => {\n const err = error as any;\n const parts = [\n err?.message,\n typeof error === \"string\" ? error : undefined,\n err?.code,\n ];\n\n try {\n if (err?.data) parts.push(JSON.stringify(err.data));\n } catch {\n // Ignore non-serializable SDK error metadata.\n }\n\n return parts.filter(Boolean).join(\" \");\n };\n\n const isInsufficientSourcesError = (error: unknown) => {\n const err = error as any;\n const message = getErrorText(error).toLowerCase();\n\n return (\n err?.code === ERROR_CODES.INSUFFICIENT_BALANCE ||\n message.includes(\"insufficient balance\") ||\n message.includes(\"sources are not enough\") ||\n (message.includes(\"source\") && message.includes(\"not enough\"))\n );\n };\n\n const isViemInvalidDecimalError = (error: unknown) =>\n getErrorText(error).toLowerCase().includes(\"not a valid decimal number\");\n\n const parseLabeledErrorDecimal = (text: string, label: string) => {\n const match = text.match(\n new RegExp(`${label}\\\\s*:\\\\s*\\\\$?\\\\s*([0-9][0-9,]*(?:\\\\.[0-9]+)?)`, \"i\")\n );\n return match ? parseFiatNumber(match[1]) : undefined;\n };\n\n const getExactOutRequestedUsd = () => {\n const amountNumber = parseFiatNumber(amount);\n if (!amountNumber || amountNumber.lte(0) || !toToken?.symbol) {\n return undefined;\n }\n\n if (activeMode === \"deposit\" && depositAmountMode === \"usd\") {\n return amountNumber;\n }\n\n const fiatValue = getFiatValue(amountNumber.toNumber(), toToken.symbol);\n return Number.isFinite(fiatValue) && fiatValue > 0\n ? new Decimal(fiatValue)\n : undefined;\n };\n\n const getExactOutAvailableSourceUsd = (\n sourceTokensOverride?: SwapTokenOption[]\n ): Decimal => {\n const sumTokensWithDestinationCredit = (\n tokens: SwapTokenOption[]\n ): Decimal => {\n const heldDestinationToken = getHeldDestinationTokenOption();\n const heldDestinationKey = getTokenSelectionKey(heldDestinationToken);\n let hasHeldDestinationToken = false;\n\n const sourceTotal = tokens.reduce((sum, token) => {\n const value = parseFiatNumber(token.balanceInFiat) ?? new Decimal(0);\n const isHeldDestinationToken =\n heldDestinationKey &&\n getTokenSelectionKey(token) === heldDestinationKey;\n if (isHeldDestinationToken) {\n hasHeldDestinationToken = true;\n }\n\n return value.gt(0) &&\n (isHeldDestinationToken || value.gte(minimumSourceUsd))\n ? sum.plus(value)\n : sum;\n }, new Decimal(0));\n\n if (!heldDestinationToken || hasHeldDestinationToken) {\n return sourceTotal;\n }\n\n const heldDestinationUsd =\n parseFiatNumber(heldDestinationToken.balanceInFiat) ?? new Decimal(0);\n return heldDestinationUsd.gt(0)\n ? sourceTotal.plus(heldDestinationUsd)\n : sourceTotal;\n };\n\n if (\n sourceTokensOverride ||\n exactOutQuoteSourceModeRef.current === \"selected\"\n ) {\n const selectedSourceTokens = sourceTokensOverride ?? fromTokens;\n return sumTokensWithDestinationCredit(selectedSourceTokens);\n }\n\n return getExactOutTotalSourceBalanceUsd();\n };\n const getExactOutTotalSourceBalanceUsd = (): Decimal => {\n const allSourceTotal: Decimal = getExactOutAvailableSourceUsd(\n getMinimumBalanceSourceTokens()\n );\n\n return allSourceTotal.gt(0) ? allSourceTotal : getSwapBalanceTotalUsd();\n };\n\n const getExactOutIntentSourceUsd = () => {\n const intentSourceUsd = (intentData?.sources ?? []).reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber((source as any).value) ?? new Decimal(0)),\n new Decimal(0)\n );\n return intentSourceUsd.gt(0) ? intentSourceUsd : undefined;\n };\n\n const getExactOutHeldDestinationUsd = () => {\n const heldDestinationToken = getHeldDestinationTokenOption();\n const value = parseFiatNumber(heldDestinationToken?.balanceInFiat);\n return value && value.gt(0) ? value : new Decimal(0);\n };\n\n const exactOutIntentIncludesHeldDestination = () => {\n const heldDestinationToken = getHeldDestinationTokenOption();\n const heldDestinationKey = getTokenSelectionKey(heldDestinationToken);\n if (!heldDestinationKey) return false;\n\n return (intentData?.sources ?? []).some((source) => {\n const chainId = source.chain?.id;\n const tokenAddress = source.token?.contractAddress;\n if (!chainId || !tokenAddress) return false;\n\n return (\n getTokenSelectionKey({\n chainId,\n contractAddress: tokenAddress,\n } as SwapTokenOption) === heldDestinationKey\n );\n });\n };\n\n const getExactOutRequiredSourceUsd = () => {\n const intentSourceUsd = getExactOutIntentSourceUsd();\n if (intentSourceUsd) return intentSourceUsd;\n return undefined;\n };\n\n const getExactOutRequiredFundingUsd = () => {\n const sourceRequiredUsd = getExactOutRequiredSourceUsd();\n if (sourceRequiredUsd) {\n const destinationCreditUsd = exactOutIntentIncludesHeldDestination()\n ? new Decimal(0)\n : getExactOutHeldDestinationUsd();\n return sourceRequiredUsd.plus(destinationCreditUsd);\n }\n\n return getExactOutRequestedUsd();\n };\n\n const getExactInSourceDeficitUsd = () => {\n if (swapType !== \"exactIn\" || fromTokens.length === 0) return undefined;\n\n return fromTokens.reduce((sum, token) => {\n const requestedAmount = parseFiatNumber(token.userAmount);\n if (!requestedAmount || requestedAmount.lte(0)) return sum;\n\n if (token.userAmountMode === \"usd\") {\n const availableUsd = parseFiatNumber(token.balanceInFiat);\n if (!availableUsd || requestedAmount.lte(availableUsd)) return sum;\n return sum.plus(requestedAmount.minus(availableUsd));\n }\n\n const availableTokenAmount = parseFiatNumber(token.balance);\n if (!availableTokenAmount || requestedAmount.lte(availableTokenAmount)) {\n return sum;\n }\n\n const missingTokenAmount = requestedAmount.minus(availableTokenAmount);\n const fiatBalance = parseFiatNumber(token.balanceInFiat);\n if (fiatBalance && availableTokenAmount.gt(0)) {\n return sum.plus(\n missingTokenAmount.mul(fiatBalance.div(availableTokenAmount))\n );\n }\n\n return sum;\n }, new Decimal(0));\n };\n\n const buildInsufficientSourcesIssue = (error: unknown): SwapQuoteIssue => {\n const errorText = getErrorText(error);\n const details =\n (error as any)?.data?.details ?? (error as any)?.details ?? {};\n const requiredFromError =\n parseFiatNumber(\n details.requiredUsd ??\n details.requiredUSD ??\n details.requiredAmountUsd ??\n details.requiredAmount ??\n details.required\n ) ?? parseLabeledErrorDecimal(errorText, \"required\");\n const availableFromError =\n parseFiatNumber(\n details.availableUsd ??\n details.availableUSD ??\n details.availableAmountUsd ??\n details.availableAmount ??\n details.available\n ) ?? parseLabeledErrorDecimal(errorText, \"available\");\n const requestedUsd = getExactOutRequiredFundingUsd();\n const availableUsd = getExactOutAvailableSourceUsd();\n const exactInSourceDeficitUsd = getExactInSourceDeficitUsd();\n\n let missingUsd =\n exactInSourceDeficitUsd && exactInSourceDeficitUsd.gt(0)\n ? exactInSourceDeficitUsd\n : requiredFromError && availableFromError\n ? requiredFromError.minus(availableFromError)\n : undefined;\n\n if (\n requestedUsd &&\n (!missingUsd || missingUsd.lte(0) || missingUsd.gt(requestedUsd.mul(5)))\n ) {\n missingUsd = requestedUsd.minus(availableUsd);\n }\n\n if (missingUsd && missingUsd.gt(0)) {\n const formattedMissing =\n missingUsd.gt(0) && missingUsd.lt(0.01)\n ? \"<$0.01\"\n : formatUsdDisplay(missingUsd);\n\n return {\n type: \"insufficientSources\",\n missingUsd: missingUsd.toDecimalPlaces(2).toFixed(),\n message: `Need ${formattedMissing} more across your assets`,\n };\n }\n\n return {\n type: \"insufficientSources\",\n message: \"Add more source balance across your assets\",\n };\n };\n\n const buildExactOutSourceBalanceIssue = (\n sourceTokensOverride?: SwapTokenOption[]\n ): SwapQuoteIssue | null => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return null;\n const requestedUsd = getExactOutRequiredFundingUsd();\n const availableUsd = getExactOutAvailableSourceUsd(sourceTokensOverride);\n if (!requestedUsd || requestedUsd.lte(0) || !availableUsd) return null;\n\n const missingUsd = requestedUsd.minus(availableUsd);\n if (missingUsd.lte(0.01)) return null;\n\n const formattedMissing =\n missingUsd.gt(0) && missingUsd.lt(0.01)\n ? \"<$0.01\"\n : formatUsdDisplay(missingUsd);\n\n return {\n type: \"insufficientSources\",\n missingUsd: missingUsd.toDecimalPlaces(2).toFixed(),\n message: `Need ${formattedMissing} more across your assets`,\n };\n };\n\n const isNativeTokenAddress = (address?: string) =>\n !address ||\n address.toLowerCase() === \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\" ||\n address.toLowerCase() === \"0x0000000000000000000000000000000000000000\";\n\n const formatReadableTokenAmount = (rawAmount: bigint, decimals: number) =>\n new Decimal(rawAmount.toString())\n .div(new Decimal(10).pow(decimals))\n .toFixed();\n\n const formatReadableTokenBalanceAmount = (\n rawAmount: bigint,\n decimals: number\n ) =>\n new Decimal(rawAmount.toString())\n .div(new Decimal(10).pow(decimals))\n .toDecimalPlaces(6)\n .toFixed();\n\n const trimDecimalString = (value: string) =>\n value.replace(/(\\.\\d*?)0+$/, \"$1\").replace(/\\.$/, \"\");\n\n const buildSourceTokenSnapshotMap = useCallback(\n (balances: UserAsset[] | null | undefined) => {\n const snapshots = new Map();\n\n for (const asset of balances ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n const chainId = breakdown.chain?.id;\n const contractAddress = breakdown.contractAddress;\n const symbol = breakdown.symbol ?? asset.symbol;\n\n if (\n !chainId ||\n !contractAddress ||\n !symbol ||\n !isSwapSupportedBySdkChainList(\n chainId,\n swapSupportedChainsAndTokens\n )\n ) {\n continue;\n }\n\n const chainMeta = CHAIN_METADATA[chainId];\n const fiatBalance = parseFiatNumber(breakdown.balanceInFiat);\n const snapshot: SwapTokenOption = {\n balance: breakdown.balance ?? \"0\",\n balanceInFiat: fiatBalance\n ? formatUsdDisplay(fiatBalance)\n : \"$0.00\",\n chainId,\n chainLogo: chainMeta?.logo ?? breakdown.chain?.logo,\n chainName: getShortChainName(\n chainId,\n chainMeta?.name ?? breakdown.chain?.name\n ),\n contractAddress,\n decimals: breakdown.decimals ?? asset.decimals ?? 18,\n logo: asset.logo ?? \"\",\n name: symbol,\n symbol,\n };\n snapshots.set(getTokenSelectionKey(snapshot), snapshot);\n }\n }\n\n return snapshots;\n },\n [swapSupportedChainsAndTokens]\n );\n\n const patchSourceTokensWithBalances = useCallback(\n (tokens: SwapTokenOption[], balances: UserAsset[]) => {\n const snapshots = buildSourceTokenSnapshotMap(balances);\n\n const updateToken = (token: SwapTokenOption): SwapTokenOption => {\n const preservedAmounts = {\n userAmount: token.userAmount,\n userAmountMode: token.userAmountMode,\n userAmountUsd: token.userAmountUsd,\n };\n\n if (token.isUnified) {\n const sourceTokens = (token.sourceTokens ?? []).map(updateToken);\n const totalBalance = sourceTokens.reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber(source.balance) ?? new Decimal(0)),\n new Decimal(0)\n );\n const totalFiat = sourceTokens.reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber(source.balanceInFiat) ?? new Decimal(0)),\n new Decimal(0)\n );\n\n return {\n ...token,\n ...preservedAmounts,\n balance: totalBalance.toDecimalPlaces(8).toFixed(),\n balanceInFiat: formatUsdDisplay(totalFiat),\n sourceTokens,\n };\n }\n\n const snapshot = snapshots.get(getTokenSelectionKey(token));\n if (!snapshot) {\n return {\n ...token,\n ...preservedAmounts,\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n chainLogo:\n token.chainLogo ??\n (token.chainId ? CHAIN_METADATA[token.chainId]?.logo : undefined),\n chainName: getShortChainName(token.chainId, token.chainName),\n };\n }\n\n return {\n ...token,\n ...snapshot,\n ...preservedAmounts,\n };\n };\n\n return tokens.map(updateToken);\n },\n [buildSourceTokenSnapshotMap]\n );\n\n const refreshSelectedSourceBalances = useCallback(async () => {\n const refreshedBalance = await fetchSwapBalance();\n const balances = refreshedBalance ?? swapBalance;\n if (!balances) return;\n\n setFromTokens((current) =>\n current.length === 0\n ? current\n : patchSourceTokensWithBalances(current, balances)\n );\n setSourceSelectionRevision((current) => current + 1);\n }, [fetchSwapBalance, patchSourceTokensWithBalances, swapBalance]);\n\n const receiveMaxSafetyMultiplier = new Decimal(\"0.9\");\n const currentSwapEntry =\n currentSwapId !== null\n ? swapHistory.find((entry) => entry.id === currentSwapId)\n : undefined;\n\n const scheduleTerminalBalanceRefresh = () => {\n if (terminalBalanceRefreshTimerRef.current) {\n clearTimeout(terminalBalanceRefreshTimerRef.current);\n }\n\n terminalBalanceRefreshTimerRef.current = setTimeout(() => {\n terminalBalanceRefreshTimerRef.current = null;\n void fetchSwapBalance();\n }, BALANCE_REFRESH_AFTER_TERMINAL_MS);\n };\n\n const patchSwapHistoryEntry = (\n id: string | null | undefined,\n patch: Partial\n ) => {\n if (!id) return;\n setSwapHistory((prev) =>\n sortSwapHistoryEntries(\n prev.map((entry) => (entry.id === id ? { ...entry, ...patch } : entry))\n )\n );\n };\n\n const patchCurrentSwapHistoryEntry = (patch: Partial) => {\n patchSwapHistoryEntry(currentSwapIdRef.current, patch);\n };\n\n const patchCurrentIntentExplorerUrl = (url?: string | null) => {\n if (!isHttpUrl(url)) return;\n if (intentUrlRef.current === url) return;\n\n intentUrlRef.current = url;\n const intentId = extractIntentIdFromUrl(url);\n patchCurrentSwapHistoryEntry({\n intentExplorerUrl: url,\n ...(intentId ? { intentId } : {}),\n });\n };\n\n const resetExplorerUrls = () => {\n const next = { sourceExplorerUrl: null, destinationExplorerUrl: null };\n explorerUrlsRef.current = next;\n setExplorerUrls(next);\n };\n\n const mergeExplorerUrls = (\n patch: Partial<{\n sourceExplorerUrl: string | null;\n destinationExplorerUrl: string | null;\n }>\n ) => {\n const next = { ...explorerUrlsRef.current, ...patch };\n explorerUrlsRef.current = next;\n setExplorerUrls(next);\n patchCurrentSwapHistoryEntry({\n sourceExplorerUrl: next.sourceExplorerUrl,\n finalExplorerUrl: next.destinationExplorerUrl ?? next.sourceExplorerUrl,\n });\n };\n\n const resetProgressEvents = () => {\n progressEventsRef.current = [];\n setProgressEvents((current) => (current.length === 0 ? current : []));\n setFailedProgressStep((current) => (current === null ? current : null));\n };\n\n const appendProgressEvent = (\n name: string,\n step: SwapStepType | BridgeStepType | undefined,\n defaultCompleted: boolean,\n event?: unknown\n ) => {\n if (!step) return;\n const completed =\n typeof (step as any).completed === \"boolean\"\n ? Boolean((step as any).completed)\n : defaultCompleted;\n\n setProgressEvents((prev) => {\n const next = [\n ...prev,\n {\n id: `${Date.now()}-${prev.length}-${(step as any).typeID ?? (step as any).type ?? name}`,\n name,\n completed,\n event,\n step,\n },\n ];\n progressEventsRef.current = next;\n return next;\n });\n };\n\n const appendProgressListEvent = (\n name: string,\n stepList: Array\n ) => {\n if (stepList.length === 0) return;\n\n setProgressEvents((prev) => {\n const next = [\n ...prev,\n {\n id: `${Date.now()}-${prev.length}-${name}`,\n name,\n completed: false,\n step: stepList[0],\n steps: stepList,\n },\n ];\n progressEventsRef.current = next;\n return next;\n });\n };\n\n const startSwapHistoryEntry = () => {\n const id = `${Date.now()}-${swapRunIdRef.current}`;\n const now = Date.now();\n const resolvedToToken =\n toToken && destinationBalance\n ? { ...toToken, balance: destinationBalance }\n : toToken;\n const entry: SwapHistoryEntry = {\n id,\n mode: activeMode,\n status: \"pending\",\n createdAt: now,\n startedAt: now,\n intentData,\n fromTokens,\n toToken: resolvedToToken,\n requestedToAmount:\n activeMode === \"deposit\" || activeMode === \"send\"\n ? previewDestinationAmount\n : undefined,\n requestedToValue:\n activeMode === \"deposit\" || activeMode === \"send\"\n ? previewToAmountUsd\n : undefined,\n recipientAddress: transferRecipientAddress,\n opportunity: selectedOpportunity,\n feeUsd: intentFeeUsd,\n sourceExplorerUrl: null,\n finalExplorerUrl: null,\n intentExplorerUrl: isHttpUrl(intentUrlRef.current)\n ? intentUrlRef.current\n : null,\n intentId: extractIntentIdFromUrl(intentUrlRef.current),\n autoRefundAvailable: false,\n };\n\n currentSwapStartedAtRef.current = 0;\n currentSwapIdRef.current = id;\n setCurrentSwapId(id);\n setSwapHistory((prev) => sortSwapHistoryEntries([entry, ...prev]));\n return id;\n };\n\n const finishCurrentSwapHistoryEntry = (\n status: \"fulfilled\" | \"failed\" | \"timeout\",\n patch: Partial = {}\n ) => {\n const now = Date.now();\n const startedAt = currentSwapStartedAtRef.current || now;\n patchSwapHistoryEntry(currentSwapIdRef.current, {\n status,\n endedAt: now,\n durationSeconds: Math.max(1, Math.round((now - startedAt) / 1000)),\n sourceExplorerUrl: explorerUrlsRef.current.sourceExplorerUrl,\n finalExplorerUrl:\n explorerUrlsRef.current.destinationExplorerUrl ??\n explorerUrlsRef.current.sourceExplorerUrl,\n ...patch,\n });\n scheduleTerminalBalanceRefresh();\n };\n\n const markSwapExecutionStarted = () => {\n if (currentSwapStartedAtRef.current > 0) return;\n const now = Date.now();\n currentSwapStartedAtRef.current = now;\n patchCurrentSwapHistoryEntry({ startedAt: now });\n };\n\n const enterSkippedSwapProgress = () => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n\n const shouldInitializeProgress = swapStepRef.current !== \"progress\";\n if (!currentSwapIdRef.current) {\n onStart?.();\n startSwapHistoryEntry();\n }\n\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setPreviewQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setSwapQuoteIssue(null);\n\n if (shouldInitializeProgress) {\n resetProgressEvents();\n swapStepsListRef.current = [];\n resetSteps();\n swapStepRef.current = \"progress\";\n setSwapStep(\"progress\");\n }\n };\n\n const cachePredictiveBaselineFromIntent = (intent: SwapIntentData) => {\n const destinationAmount = parseFiatNumber(intent.destination?.amount);\n const destinationValue = parseFiatNumber(intent.destination?.value);\n const sourceUsd = (intent.sources ?? []).reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber((source as any).value) ?? new Decimal(0)),\n new Decimal(0)\n );\n\n if (!destinationAmount || destinationAmount.lte(0)) return;\n\n const destinationUsdRate =\n destinationValue && destinationValue.gt(0)\n ? destinationValue.div(destinationAmount)\n : getUsdRateForSymbol(intent.destination?.token?.symbol);\n if (destinationUsdRate.lte(0)) return;\n\n cacheSymbolUsdRate(intent.destination?.token?.symbol, destinationUsdRate);\n\n const key = getPredictiveQuoteCacheKey();\n if (!key) return;\n\n const baseline: PredictiveQuoteBaseline = {\n destinationUsdRate: destinationUsdRate.toDecimalPlaces(18).toFixed(),\n updatedAt: Date.now(),\n };\n\n if (activeMode === \"swap\" && swapType === \"exactIn\" && sourceUsd.gt(0)) {\n baseline.exactInDestinationAmountPerSourceUsd = destinationAmount\n .div(sourceUsd)\n .toDecimalPlaces(18)\n .toFixed();\n }\n\n const resolvedDestinationValue =\n destinationValue && destinationValue.gt(0)\n ? destinationValue\n : destinationAmount.mul(destinationUsdRate);\n if (\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n resolvedDestinationValue.gt(0) &&\n sourceUsd.gt(0)\n ) {\n baseline.exactOutSourceUsdPerDestinationUsd = sourceUsd\n .div(resolvedDestinationValue)\n .toDecimalPlaces(18)\n .toFixed();\n }\n\n predictiveQuoteCacheRef.current[key] = baseline;\n };\n\n const applySwapIntent = useCallback(\n (intent: SwapIntentData) => {\n const sortedIntent = {\n ...intent,\n sources: sortIntentSourcesByUsdDesc(intent.sources ?? []),\n };\n const enrichedIntent = enrichSwapIntentTokenMetadata(sortedIntent);\n const sortedIntentSourceTokens = sortSwapTokensByUsdDesc(\n (enrichedIntent.sources ?? []).map(buildIntentSourceToken)\n );\n\n lastSwapIntentRefreshAtRef.current = Date.now();\n lastIntentSourceTokensRef.current = sortedIntentSourceTokens;\n if (\n !sourceSelectionTouched &&\n (activeMode === \"send\" ||\n (activeMode === \"deposit\" && swapType === \"exactOut\"))\n ) {\n lastAutoIntentSourceTokensRef.current = sortedIntentSourceTokens;\n }\n cacheDestinationUsdRateFromIntent(enrichedIntent);\n cachePredictiveBaselineFromIntent(enrichedIntent);\n setIntentData(enrichedIntent);\n setIntentToAmount(enrichedIntent.destination?.amount || undefined);\n setSwapQuoteIssue(null);\n\n if (\n !sourceSelectionTouched &&\n swapStepRef.current !== \"choose-swap-asset\" &&\n (activeMode === \"send\" ||\n (activeMode === \"deposit\" && swapType === \"exactOut\"))\n ) {\n syncingIntentSourcesRef.current = true;\n setFromTokens(sortedIntentSourceTokens);\n }\n\n try {\n const bridgeFees = enrichedIntent.feesAndBuffer?.bridge;\n const bridgeFeeData =\n bridgeFees && typeof bridgeFees === \"object\" ? bridgeFees : undefined;\n const collectionFee = parseFiatNumber(bridgeFeeData?.collection);\n const fulfilmentFee = parseFiatNumber(bridgeFeeData?.fulfilment);\n const executionGasFee =\n parseFiatNumber(bridgeFeeData?.caGas) ??\n (collectionFee !== undefined || fulfilmentFee !== undefined\n ? (collectionFee ?? new Decimal(0)).plus(\n fulfilmentFee ?? new Decimal(0)\n )\n : undefined);\n const bridgeGasSuppliedFee = parseFiatNumber(\n bridgeFeeData?.gasSupplied\n );\n const destinationGasSuppliedFee =\n getIntentDestinationGasUsdValue(enrichedIntent);\n const gasSuppliedFee =\n bridgeGasSuppliedFee ?? destinationGasSuppliedFee;\n const bridgeComponentsTotal = bridgeFeeData\n ? [\n executionGasFee,\n parseFiatNumber(bridgeFeeData.protocol),\n parseFiatNumber(bridgeFeeData.solver),\n gasSuppliedFee,\n ].reduce(\n (sum, value) => sum.plus(value ?? new Decimal(0)),\n new Decimal(0)\n )\n : undefined;\n const rawBridgeTotal =\n typeof bridgeFees === \"string\"\n ? parseFiatNumber(bridgeFees)\n : parseFiatNumber(bridgeFeeData?.total);\n const bridgeTotal =\n rawBridgeTotal &&\n !bridgeGasSuppliedFee &&\n destinationGasSuppliedFee &&\n destinationGasSuppliedFee.gt(0)\n ? rawBridgeTotal.plus(destinationGasSuppliedFee)\n : (rawBridgeTotal ??\n (bridgeComponentsTotal && bridgeComponentsTotal.gt(0)\n ? bridgeComponentsTotal\n : destinationGasSuppliedFee));\n\n if (bridgeTotal !== undefined) {\n setIntentFeeUsd(\n bridgeTotal.gt(0) ? bridgeTotal.toDecimalPlaces(6).toFixed() : \"0\"\n );\n } else {\n setIntentFeeUsd(undefined);\n }\n } catch (err) {\n console.warn(\"Could not resolve bridge fee total\", err);\n setIntentFeeUsd(undefined);\n }\n },\n [\n activeMode,\n fromTokens,\n getFiatValue,\n sourceSelectionTouched,\n swapType,\n swapBalance,\n swapSupportedChainsAndTokens,\n supportedChainsAndTokens,\n toToken,\n ]\n );\n\n const handleSwapIntentCallback = useCallback(\n (data: any, runId: number, quoteInputKey: string) => {\n const { intent, allow, deny, refresh } = data;\n const bridgeProvider = normalizeBridgeProvider(\n data?.bridgeProvider ??\n intent?.bridgeProvider ??\n intent?.normalizedIntent?.bridgeProvider ??\n intent?.swap?.bridgeProvider\n );\n const intentWithBridgeProvider = normalizeRenderableSwapIntentData(\n intent,\n bridgeProvider\n );\n logSdkIntentEvent(\"onIntent\", data, {\n bridgeProvider,\n currentRunId: swapRunIdRef.current,\n normalizedIntent: intentWithBridgeProvider,\n isCurrentRun: swapRunIdRef.current === runId,\n quoteInputKey,\n runId,\n });\n if (swapRunIdRef.current !== runId) {\n logSdkIntentEvent(\"ignored stale onIntent\", data, {\n currentRunId: swapRunIdRef.current,\n quoteInputKey,\n runId,\n });\n deny();\n return;\n }\n if (quoteInputKey && activeQuoteInputKeyRef.current !== quoteInputKey) {\n logSdkIntentEvent(\"ignored stale quote input onIntent\", data, {\n currentQuoteInputKey: activeQuoteInputKeyRef.current,\n quoteInputKey,\n runId,\n });\n deny();\n return;\n }\n if (!intentWithBridgeProvider) {\n console.warn(\"[NexusWidget SDK][intent] Unsupported intent shape\", {\n intent,\n raw: data,\n });\n finishIntentFetchTiming(runId, \"failed\");\n deny();\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setTxError(\"Quote unavailable\");\n return;\n }\n const resolvedQuoteInputKey = quoteInputKey;\n const normalizedRefresh =\n typeof refresh === \"function\"\n ? async (...args: unknown[]) => {\n const refreshed = await refresh(...args);\n const refreshedBridgeProvider = normalizeBridgeProvider(\n refreshed?.bridgeProvider ??\n refreshed?.normalizedIntent?.bridgeProvider ??\n refreshed?.swap?.bridgeProvider ??\n bridgeProvider\n );\n return (\n normalizeRenderableSwapIntentData(\n refreshed,\n refreshedBridgeProvider\n ) ?? refreshed\n );\n }\n : refresh;\n finishIntentFetchTiming(runId);\n providerSwapIntent.current = {\n intent: intentWithBridgeProvider as any,\n allow,\n deny,\n refresh: normalizedRefresh,\n };\n swapIntentRef.current = {\n intent: intentWithBridgeProvider,\n allow,\n deny,\n refresh: normalizedRefresh,\n runId,\n quoteInputKey: resolvedQuoteInputKey,\n };\n flushSync(() => {\n applySwapIntent(intentWithBridgeProvider);\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n });\n },\n [applySwapIntent, finishIntentFetchTiming, providerSwapIntent]\n );\n\n // Deposit-specific\n const [selectedOpportunity, setSelectedOpportunity] = useState<\n NexusWidgetDepositOpportunityConfig | undefined\n >(() => (activeMode === \"deposit\" ? configuredDeposit : undefined));\n const selectedOpportunityIdentity =\n getDepositConfigIdentity(selectedOpportunity);\n const [depositAmountMode, setDepositAmountMode] = useState<\"token\" | \"usd\">(\n \"token\"\n );\n const [depositSourceFilter, setDepositSourceFilter] =\n useState(\"all\");\n\n useEffect(() => {\n const immediateIssue = buildReceiveAmountIssue();\n applyReceiveAmountIssue(immediateIssue);\n\n if (!toToken || !getDestinationReceiveLimitUsd(toToken)) return;\n if (!parseFiatNumber(amount)?.gt(0)) return;\n if (getImmediateDestinationReceiveUsdRate(toToken)?.gt(0)) return;\n\n let cancelled = false;\n void resolveUsdRateForToken(toToken)\n .then((resolvedRate) => {\n if (cancelled) return;\n const issue = buildReceiveAmountIssue({\n destinationRate: resolvedRate.gt(0) ? resolvedRate : undefined,\n });\n applyReceiveAmountIssue(issue);\n })\n .catch(() => {\n if (!cancelled) {\n applyReceiveAmountIssue(buildReceiveAmountIssue());\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [\n activeMode,\n amount,\n depositAmountMode,\n fromTokens,\n swapType,\n toToken?.chainId,\n toToken?.chainName,\n toToken?.contractAddress,\n toToken?.priceUSD,\n toToken?.symbol,\n ]);\n\n const trackDeposit = useCallback(\n (event: string, props?: Record) => {\n const analytics = nexusSDK?.analytics;\n if (!analytics) return;\n analytics.track(event, {\n widgetSessionId: widgetSessionIdRef.current,\n widgetAttemptId: widgetAttemptIdRef.current,\n opportunityProtocol: selectedOpportunity?.protocol ?? null,\n destinationChainId: selectedOpportunity?.chainId ?? null,\n destinationToken: selectedOpportunity?.tokenSymbol ?? null,\n ...props,\n });\n },\n [nexusSDK, selectedOpportunity]\n );\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (!nexusSDK?.analytics) return;\n if (widgetOpenedFiredRef.current) return;\n widgetOpenedFiredRef.current = true;\n widgetOpenedTsRef.current = Date.now();\n rotateAttempt();\n trackDeposit(\"deposit_widget_opened\", {\n embed: Boolean(embed),\n depositConfigured: Boolean(configuredDeposit),\n prefillAmountPresent: Boolean(config.prefill?.amount),\n });\n }, [\n activeMode,\n nexusSDK,\n embed,\n configuredDeposit,\n config.prefill,\n rotateAttempt,\n trackDeposit,\n ]);\n\n useEffect(() => {\n analyticsRef.current = nexusSDK?.analytics ?? null;\n }, [nexusSDK]);\n\n useEffect(() => {\n selectedOpportunityRef.current = selectedOpportunity;\n }, [selectedOpportunity]);\n\n useEffect(() => {\n return () => {\n if (!widgetOpenedFiredRef.current) return;\n const analytics = analyticsRef.current;\n if (!analytics) return;\n const opp = selectedOpportunityRef.current;\n analytics.track(\"deposit_widget_closed\", {\n widgetSessionId: widgetSessionIdRef.current,\n widgetAttemptId: widgetAttemptIdRef.current,\n opportunityProtocol: opp?.protocol ?? null,\n lastStep: swapStepRef.current,\n reachedTerminal: reachedTerminalRef.current,\n hadSimulationSuccess: hadSimulationSuccessRef.current,\n hadPreviewViewed: hadPreviewViewedRef.current,\n timeInWidgetMs: Date.now() - widgetOpenedTsRef.current,\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const toTokenFromOpportunity = (\n opp: NexusWidgetDepositOpportunityMetadata\n ): SwapTokenOption => {\n const citreaToken = findCitreaReceiveToken({\n address: opp.tokenAddress,\n chainId: opp.chainId,\n symbol: opp.tokenSymbol,\n });\n const chainTokens = supportedChainsAndTokens?.find(\n (chain) => chain.id === opp.chainId\n )?.tokens;\n const matchedToken = chainTokens?.find(\n (token) =>\n token.contractAddress.toLowerCase() ===\n opp.tokenAddress.toLowerCase() || token.symbol === opp.tokenSymbol\n );\n const tokenSymbol =\n citreaToken?.symbol ?? matchedToken?.symbol ?? opp.tokenSymbol;\n const tokenMeta =\n TOKEN_METADATA[tokenSymbol as keyof typeof TOKEN_METADATA];\n\n return {\n chainId: opp.chainId,\n contractAddress: citreaToken?.contractAddress ?? opp.tokenAddress,\n symbol: tokenSymbol,\n name: matchedToken?.name || citreaToken?.name || tokenSymbol,\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n decimals:\n matchedToken?.decimals ??\n citreaToken?.decimals ??\n opp.tokenDecimals ??\n tokenMeta?.decimals ??\n 18,\n logo:\n opp.tokenLogo ||\n matchedToken?.logo ||\n citreaToken?.logo ||\n tokenMeta?.logo,\n chainName: getShortChainName(\n opp.chainId,\n CHAIN_METADATA[opp.chainId]?.name ?? citreaToken?.chainName\n ),\n chainLogo: CHAIN_METADATA[opp.chainId]?.logo ?? citreaToken?.chainLogo,\n };\n };\n\n const getDestinationBalanceFromSwapBalances = (token?: SwapTokenOption) => {\n if (!token?.chainId || !token.contractAddress) return null;\n\n const targetAddress = token.contractAddress.toLowerCase();\n const targetSymbol = token.symbol.toUpperCase();\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n if (breakdown.chain?.id !== token.chainId) continue;\n\n const breakdownAddress = breakdown.contractAddress?.toLowerCase();\n const addressMatches =\n (breakdownAddress && breakdownAddress === targetAddress) ||\n (isNativeTokenAddress(breakdownAddress) &&\n isNativeTokenAddress(targetAddress));\n const symbolMatches =\n (breakdown.symbol ?? asset.symbol ?? \"\").toUpperCase() ===\n targetSymbol;\n\n if (!addressMatches && !symbolMatches) continue;\n\n const balance = parseFiatNumber(breakdown.balance);\n if (!balance) return null;\n\n return balance.toFixed();\n }\n }\n\n return null;\n };\n\n const resolvePrefillToken = useCallback(\n (pair?: RuntimeDestinationPair) => {\n if (!pair?.token || !pair.chain) return undefined;\n\n const normalizeAddress = (address?: string) => {\n if (!address) return \"\";\n return isNativeTokenAddress(address)\n ? zeroAddress\n : address.toLowerCase();\n };\n const targetAddress = normalizeAddress(pair.token);\n\n const balanceToken = deriveTokenOptions(\n swapBalance ?? [],\n swapSupportedChainsAndTokens\n ).find(\n (token) =>\n token.chainId === pair.chain &&\n normalizeAddress(token.contractAddress) === targetAddress\n );\n if (balanceToken) return balanceToken;\n\n const chain = supportedChainsAndTokens?.find(\n (item) => item.id === pair.chain\n );\n const matchedToken = chain?.tokens?.find(\n (token) => normalizeAddress(token.contractAddress) === targetAddress\n );\n const citreaToken = findCitreaReceiveToken({\n address: pair.token,\n chainId: pair.chain,\n });\n const tokenAddressSymbol = Object.entries(\n TOKEN_CONTRACT_ADDRESSES as Record>\n ).find(\n ([, addresses]) =>\n normalizeAddress(addresses[pair.chain]) === targetAddress\n )?.[0];\n const chainMeta = CHAIN_METADATA[pair.chain];\n const isNativePrefill = isNativeTokenAddress(pair.token);\n const tokenSymbol =\n matchedToken?.symbol ??\n citreaToken?.symbol ??\n pair.symbol ??\n tokenAddressSymbol ??\n (isNativePrefill ? chainMeta?.nativeCurrency?.symbol : undefined) ??\n \"Token\";\n const tokenMeta =\n TOKEN_METADATA[tokenSymbol as keyof typeof TOKEN_METADATA];\n\n if (\n !chain &&\n !matchedToken &&\n !citreaToken &&\n !tokenAddressSymbol &&\n !pair.symbol &&\n !isNativePrefill\n ) {\n return undefined;\n }\n\n return {\n chainId: pair.chain,\n contractAddress: citreaToken?.contractAddress ?? pair.token,\n symbol: tokenSymbol,\n name: matchedToken?.name || citreaToken?.name || tokenSymbol,\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n decimals:\n matchedToken?.decimals ??\n citreaToken?.decimals ??\n pair.decimals ??\n tokenMeta?.decimals ??\n (isNativePrefill ? chainMeta?.nativeCurrency?.decimals : undefined) ??\n 18,\n logo:\n matchedToken?.logo ||\n citreaToken?.logo ||\n pair.logo ||\n tokenMeta?.logo,\n chainName: getShortChainName(\n pair.chain,\n chain?.name ?? chainMeta?.name ?? citreaToken?.chainName\n ),\n chainLogo: chainMeta?.logo ?? chain?.logo ?? citreaToken?.chainLogo,\n } satisfies SwapTokenOption;\n },\n [supportedChainsAndTokens, swapBalance]\n );\n\n useEffect(() => {\n if (activeMode !== \"swap\") return;\n\n const sourcePrefill = config.prefill?.source;\n const destinationPrefill = config.prefill?.destination;\n if (!sourcePrefill && !destinationPrefill) return;\n\n const prefillKey = [\n sourcePrefill\n ? `source:${sourcePrefill.chain}:${sourcePrefill.token.toLowerCase()}`\n : \"\",\n destinationPrefill\n ? `destination:${destinationPrefill.chain}:${destinationPrefill.token.toLowerCase()}`\n : \"\",\n config.prefill?.amount ? `amount:${config.prefill.amount}` : \"\",\n ].join(\"|\");\n\n if (appliedTokenPrefillRef.current === prefillKey) return;\n\n const sourceToken = resolvePrefillToken(sourcePrefill);\n const destinationToken = resolvePrefillToken(destinationPrefill);\n\n if (sourcePrefill && !sourceToken) return;\n if (destinationPrefill && !destinationToken) return;\n\n if (sourceToken) {\n setFromTokens((current) => {\n const nextSourceToken = {\n ...sourceToken,\n userAmount: config.prefill?.amount ?? \"\",\n };\n const currentSourceToken = current[0];\n if (\n current.length === 1 &&\n isSameTokenSelection(currentSourceToken, nextSourceToken) &&\n currentSourceToken.userAmount === nextSourceToken.userAmount\n ) {\n return current;\n }\n return [nextSourceToken];\n });\n setSourceSelectionTouched(true);\n }\n if (destinationToken) {\n setToToken((current) =>\n isSameTokenSelection(current, destinationToken)\n ? current\n : destinationToken\n );\n }\n setSwapType(\"exactIn\");\n appliedTokenPrefillRef.current = prefillKey;\n }, [\n activeMode,\n config.prefill?.amount,\n config.prefill?.destination?.chain,\n config.prefill?.destination?.decimals,\n config.prefill?.destination?.logo,\n config.prefill?.destination?.symbol,\n config.prefill?.destination?.token,\n config.prefill?.source?.chain,\n config.prefill?.source?.decimals,\n config.prefill?.source?.logo,\n config.prefill?.source?.symbol,\n config.prefill?.source?.token,\n resolvePrefillToken,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"send\") return;\n\n const sendPrefill =\n config.prefill?.token && config.prefill?.chain\n ? {\n token: config.prefill.token,\n chain: config.prefill.chain,\n }\n : config.prefill?.destination;\n if (!sendPrefill) return;\n\n const prefillKey = `send:${sendPrefill.chain}:${sendPrefill.token.toLowerCase()}`;\n if (appliedTokenPrefillRef.current === prefillKey) return;\n\n const token = resolvePrefillToken(sendPrefill);\n if (!token) return;\n\n setToToken(token);\n setSwapType(\"exactOut\");\n appliedTokenPrefillRef.current = prefillKey;\n }, [\n activeMode,\n config.prefill?.chain,\n config.prefill?.destination?.chain,\n config.prefill?.destination?.decimals,\n config.prefill?.destination?.logo,\n config.prefill?.destination?.symbol,\n config.prefill?.destination?.token,\n config.prefill?.token,\n resolvePrefillToken,\n ]);\n\n useEffect(() => {\n if (config.prefill?.amount) setAmount(config.prefill.amount);\n if (config.prefill?.recipient)\n setRecipientAddress(config.prefill.recipient);\n }, [config.prefill?.amount, config.prefill?.recipient]);\n\n useEffect(() => {\n setDestinationBalance(null);\n\n const balanceToken =\n toToken ??\n (activeMode === \"deposit\" && selectedOpportunity\n ? toTokenFromOpportunity(selectedOpportunity)\n : undefined);\n\n if (!balanceToken?.chainId || !ownerAddress) return;\n\n const swapBalanceValue =\n getDestinationBalanceFromSwapBalances(balanceToken);\n if (swapBalanceValue) {\n setDestinationBalance(swapBalanceValue);\n }\n }, [\n activeMode,\n ownerAddress,\n selectedOpportunity?.chainId,\n selectedOpportunity?.tokenAddress,\n selectedOpportunity?.tokenLogo,\n selectedOpportunity?.tokenSymbol,\n swapBalance,\n toToken?.chainId,\n toToken?.chainName,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.symbol,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\" || !configuredDeposit) return;\n setSelectedOpportunity((current) =>\n isSameDepositConfig(current, configuredDeposit)\n ? current\n : configuredDeposit\n );\n setSwapType(\"exactOut\");\n setToToken((current) => {\n const next = {\n ...toTokenFromOpportunity(configuredDeposit),\n balance: current?.balance ?? \"0\",\n balanceInFiat: current?.balanceInFiat ?? \"$0.00\",\n };\n if (\n current &&\n current.chainId === next.chainId &&\n current.contractAddress.toLowerCase() ===\n next.contractAddress.toLowerCase() &&\n current.symbol === next.symbol &&\n current.decimals === next.decimals &&\n current.logo === next.logo &&\n current.chainLogo === next.chainLogo &&\n current.chainName === next.chainName &&\n current.balance === next.balance &&\n current.balanceInFiat === next.balanceInFiat\n ) {\n return current;\n }\n return next;\n });\n }, [\n activeMode,\n configuredDepositIdentity,\n configuredDeposit?.chainId,\n configuredDeposit?.tokenAddress,\n configuredDeposit?.tokenLogo,\n configuredDeposit?.tokenSymbol,\n supportedChainsAndTokens,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\" || !selectedOpportunity) return;\n setToToken((current) => {\n const next = {\n ...toTokenFromOpportunity(selectedOpportunity),\n balance: current?.balance ?? \"0\",\n balanceInFiat: current?.balanceInFiat ?? \"$0.00\",\n };\n if (\n current &&\n current.chainId === next.chainId &&\n current.contractAddress.toLowerCase() ===\n next.contractAddress.toLowerCase() &&\n current.symbol === next.symbol &&\n current.decimals === next.decimals &&\n current.logo === next.logo &&\n current.chainLogo === next.chainLogo &&\n current.chainName === next.chainName &&\n current.balance === next.balance &&\n current.balanceInFiat === next.balanceInFiat\n ) {\n return current;\n }\n return next;\n });\n }, [activeMode, selectedOpportunity, supportedChainsAndTokens]);\n\n useEffect(() => {\n if (activeMode !== \"send\") return;\n setSwapType(\"exactOut\");\n }, [activeMode]);\n\n useEffect(() => {\n if (activeMode === \"swap\" && swapType !== \"exactIn\") {\n setSwapType(\"exactIn\");\n }\n }, [activeMode, swapType]);\n\n useEffect(() => {\n if (!toToken?.symbol) return;\n if (getFiatValue(1, toToken.symbol) > 0) return;\n\n let cancelled = false;\n void resolveTokenUsdRate(toToken.symbol).catch((error) => {\n if (!cancelled) {\n console.warn(\"Unable to resolve Nexus Widget token USD rate\", {\n symbol: toToken.symbol,\n error,\n });\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [activeMode, getFiatValue, resolveTokenUsdRate, toToken?.symbol]);\n\n // Balance helpers\n const activeBalanceArray = swapBalance;\n const selectedToken = config.prefill?.token ?? \"USDC\";\n const currentAsset =\n activeBalanceArray?.find((a) => a.symbol === selectedToken) ||\n activeBalanceArray?.[0];\n const maxBalance = currentAsset?.balance\n ? String(currentAsset.balance)\n : undefined;\n const usdValue = getFiatValue(\n Number(amount) || 0,\n currentAsset?.symbol || \"USDC\"\n );\n const getDepositTokenUsdRate = () => {\n if (selectedOpportunity?.tokenSymbol) {\n const fiat = getFiatValue(1, selectedOpportunity.tokenSymbol);\n if (Number.isFinite(fiat) && fiat > 0) {\n return new Decimal(fiat);\n }\n }\n\n if (toToken) {\n const tokenRate = getTokenUsdRate(toToken);\n if (tokenRate.gt(0)) return tokenRate;\n }\n\n return getCachedDestinationUsdRate(toToken) ?? new Decimal(0);\n };\n const getDepositTokenAmountForQuote = () => {\n const parsedAmount = parseFiatNumber(amount) ?? new Decimal(0);\n if (parsedAmount.lte(0)) return undefined;\n if (depositAmountMode === \"token\") return parsedAmount;\n\n const rate = getDepositTokenUsdRate();\n if (rate.lte(0)) return undefined;\n return parsedAmount.div(rate);\n };\n const depositTokenAmountForQuote = getDepositTokenAmountForQuote();\n const depositQuoteAmountKey = depositTokenAmountForQuote?.toFixed() ?? \"\";\n const depositUsdDecimal =\n depositAmountMode === \"usd\"\n ? (parseFiatNumber(amount) ?? new Decimal(0))\n : depositTokenAmountForQuote\n ? depositTokenAmountForQuote.mul(getDepositTokenUsdRate())\n : new Decimal(0);\n const depositUsdDisplay = depositUsdDecimal.toDecimalPlaces(2).toFixed();\n const depositTokenDisplay =\n depositTokenAmountForQuote\n ?.toDecimalPlaces(\n getCappedTokenDisplayDecimals(toToken?.decimals),\n Decimal.ROUND_DOWN\n )\n .toFixed() ?? \"0\";\n const isExactOutMode = activeMode === \"deposit\" || activeMode === \"send\";\n const getActiveTotalBalanceUsd = () =>\n isExactOutMode\n ? getExactOutTotalSourceBalanceUsd()\n : getSwapBalanceTotalUsd();\n const getTotalBalancePercentUsdAmount = (pct: number) => {\n const ratio =\n isExactOutMode && pct === 100\n ? receiveMaxSafetyMultiplier\n : new Decimal(pct).div(100);\n return getActiveTotalBalanceUsd().mul(ratio);\n };\n const getExactOutDestinationUsdRate = (token: SwapTokenOption) => {\n if (activeMode === \"deposit\") {\n return getDepositTokenUsdRate();\n }\n return getTokenUsdRate(token);\n };\n const getExactOutPercentAmountFromBalance = (\n token: SwapTokenOption,\n pct: number,\n preferUsd: boolean\n ) => {\n const usdAmount = getTotalBalancePercentUsdAmount(pct);\n if (usdAmount.lte(0)) return undefined;\n\n if (preferUsd) {\n return {\n amount: usdAmount.toDecimalPlaces(2, Decimal.ROUND_DOWN).toFixed(),\n mode: \"usd\" as const,\n };\n }\n\n const rate = getExactOutDestinationUsdRate(token);\n if (rate.lte(0)) return undefined;\n\n return {\n amount: usdAmount\n .div(rate)\n .toDecimalPlaces(\n getCappedTokenDisplayDecimals(token.decimals),\n Decimal.ROUND_DOWN\n )\n .toFixed(),\n mode: \"token\" as const,\n };\n };\n const depositSourceTargetUsdKey =\n activeMode === \"deposit\"\n ? (getDepositSourceTargetUsd()?.toFixed() ?? \"\")\n : \"\";\n const normalizedQuoteAmountKey = parseFiatNumber(amount)?.toFixed() ?? \"\";\n const quoteRecipientKey =\n activeMode === \"swap\"\n ? effectiveRecipientAddress\n : activeMode === \"send\"\n ? recipientAddress\n : \"\";\n const activeQuoteInputKey = [\n activeMode,\n swapType,\n normalizedQuoteAmountKey,\n toTokenQuoteKey,\n quoteRecipientKey.toLowerCase(),\n activeMode === \"swap\" ? fromTokensQuoteKey : \"\",\n activeMode === \"deposit\"\n ? [\n depositAmountMode,\n depositQuoteAmountKey,\n selectedOpportunityIdentity,\n depositSourceTargetUsdKey,\n depositSourceFilter,\n sourceSelectionTouched ? \"manual\" : \"auto\",\n sourceSelectionRevision,\n exactOutQuoteSourceMode,\n ].join(\":\")\n : \"\",\n activeMode === \"send\"\n ? [\n sourceSelectionTouched ? \"manual\" : \"auto\",\n sourceSelectionRevision,\n exactOutQuoteSourceMode,\n ].join(\":\")\n : \"\",\n ].join(\"|\");\n\n const exactOutAutoSourceInputKey = [\n activeMode,\n normalizedQuoteAmountKey,\n toTokenQuoteKey,\n quoteRecipientKey.toLowerCase(),\n activeMode === \"deposit\"\n ? [\n depositAmountMode,\n depositQuoteAmountKey,\n selectedOpportunityIdentity,\n depositSourceTargetUsdKey,\n ].join(\":\")\n : \"\",\n ].join(\"|\");\n\n activeQuoteInputKeyRef.current = activeQuoteInputKey;\n\n useEffect(() => {\n lastAutoIntentSourceTokensRef.current = [];\n }, [exactOutAutoSourceInputKey]);\n\n useEffect(() => {\n setTxError(null);\n }, [activeQuoteInputKey]);\n const hasCurrentQuoteIntent = Boolean(\n intentData &&\n swapIntentRef.current &&\n swapIntentRef.current.runId === swapRunIdRef.current &&\n swapIntentRef.current.quoteInputKey === activeQuoteInputKey\n );\n\n useEffect(() => {\n if (swapStep !== \"idle\") return;\n if (!hasCurrentQuoteIntent) return;\n if (sourceSelectionTouched) return;\n if (\n activeMode !== \"send\" &&\n !(activeMode === \"deposit\" && swapType === \"exactOut\")\n ) {\n return;\n }\n\n const nextTokens = lastIntentSourceTokensRef.current;\n if (nextTokens.length === 0) return;\n\n setFromTokens((current) => {\n if (\n getSourceTokenListSyncKey(current) ===\n getSourceTokenListSyncKey(nextTokens)\n ) {\n return current;\n }\n\n syncingIntentSourcesRef.current = true;\n return nextTokens;\n });\n }, [\n activeMode,\n hasCurrentQuoteIntent,\n sourceSelectionTouched,\n swapStep,\n swapType,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (!nexusSDK?.analytics) return;\n const parsed = parseFiatNumber(amount);\n if (!parsed || parsed.lte(0)) return;\n if (amount === amountEnteredLastValueRef.current) return;\n const timeout = setTimeout(() => {\n amountEnteredLastValueRef.current = amount;\n trackDeposit(\"deposit_amount_entered\", {\n amountToken: depositTokenDisplay,\n amountUsd: Number(depositUsdDisplay) || 0,\n inputMethod: lastInputMethodRef.current,\n });\n lastInputMethodRef.current = \"typed\";\n }, 500);\n return () => clearTimeout(timeout);\n }, [\n amount,\n activeMode,\n nexusSDK,\n depositTokenDisplay,\n depositUsdDisplay,\n trackDeposit,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (intentData) hadSimulationSuccessRef.current = true;\n }, [intentData, activeMode]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (sourceSelectionTouched) return;\n previousAutoSourceCountRef.current = (intentData?.sources ?? []).length;\n }, [intentData, activeMode, sourceSelectionTouched]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n const prev = prevSourceTouchedRef.current;\n const curr = sourceSelectionTouched;\n if (prev === curr) return;\n prevSourceTouchedRef.current = curr;\n if (!prev && curr) {\n trackDeposit(\"deposit_source_selection_changed\", {\n sourceCount: fromTokens.length,\n sourceChainIds: fromTokens.map((t) => t.chainId).filter(Boolean),\n sourceTokenSymbols: fromTokens.map((t) => t.symbol).filter(Boolean),\n previousSourceCount: previousAutoSourceCountRef.current,\n });\n } else if (prev && !curr) {\n trackDeposit(\"deposit_source_selection_reverted_to_auto\", {\n previousSourceCount: fromTokens.length,\n });\n }\n }, [sourceSelectionTouched, activeMode, fromTokens, trackDeposit]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (swapStep !== \"preview-intent\") return;\n if (intentLoading) return;\n if (!intentData) return;\n if (hadPreviewViewedRef.current) return;\n hadPreviewViewedRef.current = true;\n previewViewedTsRef.current = Date.now();\n trackDeposit(\"deposit_preview_viewed\", {\n totalFeeUsd: Number(intentFeeUsd) || 0,\n toAmountUsd: Number(depositUsdDisplay) || 0,\n sourceCount: (intentData?.sources ?? []).length,\n });\n }, [\n swapStep,\n intentLoading,\n intentData,\n activeMode,\n intentFeeUsd,\n depositUsdDisplay,\n trackDeposit,\n ]);\n const requiredDestinationTokenAmount =\n activeMode === \"deposit\"\n ? depositTokenAmountForQuote\n : activeMode === \"send\"\n ? parseFiatNumber(amount)\n : undefined;\n const canRefreshExactOutQuote = () =>\n activeMode === \"deposit\"\n ? Boolean(\n hasPositiveDecimalInput(amount) &&\n toToken &&\n selectedOpportunity &&\n depositTokenAmountForQuote &&\n depositTokenAmountForQuote.gt(0)\n )\n : activeMode === \"send\"\n ? Boolean(hasPositiveDecimalInput(amount) && toToken)\n : false;\n const invalidateExactOutQuoteForRefresh = (options?: {\n sourceTokens?: SwapTokenOption[];\n }) => {\n immediateQuoteAfterSourceEditRef.current = true;\n const receiveIssue = buildReceiveAmountIssue({\n sourceTokens: options?.sourceTokens,\n });\n applyReceiveAmountIssue(receiveIssue);\n const configuredIssue = buildConfiguredAmountIssue();\n if (configuredIssue) {\n clearPreviewForBlockingAmountIssue();\n }\n const sourceBalanceIssue = buildExactOutSourceBalanceIssue(\n options?.sourceTokens\n );\n if (sourceBalanceIssue) {\n clearPreviewForBlockingAmountIssue();\n setSwapQuoteIssue(sourceBalanceIssue);\n }\n const shouldLoadQuote = Boolean(\n !receiveIssue &&\n !configuredIssue &&\n !sourceBalanceIssue &&\n nexusSDK &&\n canRefreshExactOutQuote()\n );\n if (!receiveIssue && !configuredIssue && !sourceBalanceIssue) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: shouldLoadQuote });\n }\n if (shouldLoadQuote) {\n setQuoteRefreshing(true);\n setTxError(null);\n setSwapQuoteIssue(null);\n }\n return shouldLoadQuote;\n };\n\n useEffect(() => {\n if (\n activeMode !== \"swap\" ||\n swapStep !== \"idle\" ||\n swapType !== \"exactIn\"\n ) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current\n );\n return;\n }\n\n const sources = getPredictiveExactInSourceTokens();\n const key = getPredictiveQuoteCacheKey();\n if (!toToken || sources.length === 0 || !key) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current\n );\n return;\n }\n\n const runId = ++predictiveQuoteRunRef.current;\n let cancelled = false;\n\n void (async () => {\n const baseline = predictiveQuoteCacheRef.current[key];\n const cachedDestinationRate = parseFiatNumber(\n baseline?.destinationUsdRate\n );\n const destinationRate =\n cachedDestinationRate && cachedDestinationRate.gt(0)\n ? cachedDestinationRate\n : await resolveUsdRateForToken(toToken);\n\n if (cancelled || runId !== predictiveQuoteRunRef.current) return;\n if (destinationRate.lte(0)) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current\n );\n return;\n }\n\n let sourceUsd = new Decimal(0);\n for (const source of sources) {\n const sourceAmount =\n parseFiatNumber(source.userAmount) ?? new Decimal(0);\n if (sourceAmount.lte(0)) continue;\n\n if (source.userAmountMode === \"usd\") {\n sourceUsd = sourceUsd.plus(sourceAmount);\n continue;\n }\n\n const sourceRate = await resolveUsdRateForToken(source);\n if (cancelled || runId !== predictiveQuoteRunRef.current) return;\n if (sourceRate.lte(0)) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current\n );\n return;\n }\n sourceUsd = sourceUsd.plus(sourceAmount.mul(sourceRate));\n }\n\n if (sourceUsd.lte(0)) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current\n );\n return;\n }\n\n const cachedAmountPerSourceUsd = parseFiatNumber(\n baseline?.exactInDestinationAmountPerSourceUsd\n );\n const predictedDestinationAmount =\n cachedAmountPerSourceUsd && cachedAmountPerSourceUsd.gt(0)\n ? sourceUsd.mul(cachedAmountPerSourceUsd)\n : sourceUsd\n .mul(BASIS_POINTS - PREDICTIVE_EXACT_IN_DISCOUNT_BPS)\n .div(BASIS_POINTS)\n .div(destinationRate);\n const predictedDestinationUsd =\n cachedAmountPerSourceUsd && cachedAmountPerSourceUsd.gt(0)\n ? predictedDestinationAmount.mul(destinationRate)\n : sourceUsd\n .mul(BASIS_POINTS - PREDICTIVE_EXACT_IN_DISCOUNT_BPS)\n .div(BASIS_POINTS);\n\n if (\n cancelled ||\n runId !== predictiveQuoteRunRef.current ||\n predictedDestinationAmount.lte(0)\n ) {\n return;\n }\n\n setPredictiveQuote({\n key,\n mode: \"exactIn\",\n toAmount: getPredictiveDisplayAmount(\n predictedDestinationAmount,\n toToken\n ),\n toUsd: predictedDestinationUsd.toDecimalPlaces(6).toFixed(),\n });\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n activeMode,\n amount,\n fromTokens,\n swapStep,\n swapType,\n toToken?.chainId,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.symbol,\n ]);\n\n useEffect(() => {\n if (\n (activeMode !== \"deposit\" && activeMode !== \"send\") ||\n swapStep !== \"idle\" ||\n swapType !== \"exactOut\" ||\n !nexusSDK\n ) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactOut\" ? null : current\n );\n return;\n }\n\n const parsedAmount = parseFiatNumber(amount);\n const key = getPredictiveQuoteCacheKey();\n if (\n !toToken ||\n !parsedAmount ||\n parsedAmount.lte(0) ||\n !key ||\n (activeMode === \"deposit\" && !selectedOpportunity)\n ) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactOut\" ? null : current\n );\n return;\n }\n\n const runId = ++predictiveQuoteRunRef.current;\n let cancelled = false;\n\n void (async () => {\n const baseline = predictiveQuoteCacheRef.current[key];\n const cachedDestinationRate = parseFiatNumber(\n baseline?.destinationUsdRate\n );\n const destinationRate =\n cachedDestinationRate && cachedDestinationRate.gt(0)\n ? cachedDestinationRate\n : await resolveUsdRateForToken(toToken);\n\n if (cancelled || runId !== predictiveQuoteRunRef.current) return;\n if (destinationRate.lte(0)) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactOut\" ? null : current\n );\n return;\n }\n\n const destinationAmount =\n activeMode === \"deposit\" && depositAmountMode === \"usd\"\n ? parsedAmount.div(destinationRate)\n : parsedAmount;\n const destinationUsd =\n activeMode === \"deposit\" && depositAmountMode === \"usd\"\n ? parsedAmount\n : destinationAmount.mul(destinationRate);\n const destinationCoverage = getExactOutDestinationBalanceCoverage({\n requestedAmount: destinationAmount,\n requestedUsd: destinationUsd,\n token: toToken,\n });\n const destinationUsdNeedingSources = Decimal.max(\n destinationUsd.minus(destinationCoverage?.usd ?? new Decimal(0)),\n new Decimal(0)\n );\n const cachedSourceUsdRatio = parseFiatNumber(\n baseline?.exactOutSourceUsdPerDestinationUsd\n );\n const requiredSourceUsd = getPredictiveExactOutSourceTargetUsd(\n destinationUsdNeedingSources,\n cachedSourceUsdRatio\n );\n const sources = requiredSourceUsd.gt(0)\n ? await buildPredictiveExactOutSources(requiredSourceUsd)\n : [];\n\n if (\n cancelled ||\n runId !== predictiveQuoteRunRef.current ||\n (requiredSourceUsd.gt(0) && sources.length === 0)\n ) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactOut\" ? null : current\n );\n return;\n }\n\n setPredictiveQuote({\n key,\n mode: \"exactOut\",\n sources,\n toAmount: getPredictiveDisplayAmount(destinationAmount, toToken),\n toUsd: destinationUsd.toDecimalPlaces(6).toFixed(),\n });\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n activeMode,\n amount,\n depositAmountMode,\n destinationBalance,\n fromTokensQuoteKey,\n nexusSDK,\n selectedOpportunityIdentity,\n sourceSelectionRevision,\n swapBalance,\n swapStep,\n swapType,\n toToken?.balance,\n toToken?.balanceInFiat,\n toToken?.chainId,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.symbol,\n ]);\n\n const resolvedDepositSourceTokens = useMemo(() => {\n if (activeMode !== \"deposit\" || !swapBalance) return [];\n const selection = getResolvedDepositSourceSelection();\n return getDepositSourceTokensForIds(selection.selectedSourceIds);\n }, [\n activeMode,\n depositSourceFilter,\n depositQuoteAmountKey,\n depositSourceTargetUsdKey,\n depositUsdDecimal.toFixed(),\n fromTokensQuoteKey,\n selectedOpportunity?.chainId,\n selectedOpportunity?.tokenAddress,\n selectedOpportunity?.tokenSymbol,\n sourceSelectionRevision,\n sourceSelectionTouched,\n swapBalance,\n toToken?.chainId,\n toToken?.contractAddress,\n toToken?.symbol,\n ]);\n const lockedDestinationSourceTokens = useMemo(() => {\n if (\n (activeMode !== \"deposit\" && activeMode !== \"send\") ||\n !toToken?.chainId ||\n !requiredDestinationTokenAmount ||\n requiredDestinationTokenAmount.lte(0)\n ) {\n return [];\n }\n\n const heldDestinationToken = getHeldDestinationTokenOption();\n return heldDestinationToken ? [heldDestinationToken] : [];\n }, [\n activeMode,\n requiredDestinationTokenAmount?.toFixed(),\n swapBalance,\n toToken?.chainId,\n toToken?.chainLogo,\n toToken?.chainName,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.logo,\n toToken?.symbol,\n ]);\n\n const setSourcePickerDraftSelection = useCallback(\n (tokens: SwapTokenOption[]) => {\n const nextTokens = tokens.map((token) => ({\n ...token,\n userAmount: \"\",\n }));\n sourcePickerDraftTokensRef.current = nextTokens;\n setSourcePickerDraftTokens(nextTokens);\n },\n []\n );\n\n const getAutoExactOutSourceTokensForPicker = useCallback(() => {\n const autoIntentTokens = lastAutoIntentSourceTokensRef.current;\n if (autoIntentTokens.length > 0) {\n return autoIntentTokens;\n }\n\n if (activeMode === \"deposit\") {\n const selection = getResolvedDepositSourceSelection({\n filter: \"all\",\n isManualSelection: false,\n });\n const resolvedTokens = getDepositSourceTokensForIds(\n selection.selectedSourceIds\n );\n if (resolvedTokens.length > 0) {\n return resolvedTokens;\n }\n }\n\n if (activeMode === \"send\") {\n const gasCapable = getGasCapableBalanceSourceTokens();\n if (gasCapable.length > 0) {\n return gasCapable;\n }\n }\n\n return sourceSelectionTouched ? [] : fromTokens;\n }, [\n activeMode,\n fromTokens,\n getDepositSourceTokensForIds,\n getGasCapableBalanceSourceTokens,\n getResolvedDepositSourceSelection,\n sourceSelectionTouched,\n ]);\n\n const resetSourcePickerDraft = useCallback(() => {\n sourcePickerDraftTokensRef.current = null;\n setSourcePickerDraftTokens(null);\n }, []);\n\n const beginSourcePickerEdit = useCallback(() => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") {\n resetSourcePickerDraft();\n return;\n }\n\n sourcePickerDraftDepositFilterRef.current = depositSourceFilter;\n sourcePickerDraftTouchedRef.current = sourceSelectionTouched;\n sourcePickerDraftModeRef.current = exactOutQuoteSourceModeRef.current;\n setSourcePickerDraftSelection(fromTokens);\n }, [\n activeMode,\n depositSourceFilter,\n fromTokens,\n resetSourcePickerDraft,\n setSourcePickerDraftSelection,\n sourceSelectionTouched,\n ]);\n\n const handleSourcePickerCancel = useCallback(() => {\n resetSourcePickerDraft();\n closeDrawerToIdle();\n }, [closeDrawerToIdle, resetSourcePickerDraft]);\n\n const handleSourcePickerDraftSelectionChange = useCallback(\n (tokens: SwapTokenOption[], tab: SourceFilterTab = \"custom\") => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n\n setSourcePickerDraftSelection(tokens);\n sourcePickerDraftTouchedRef.current = true;\n sourcePickerDraftModeRef.current = \"selected\";\n sourcePickerDraftDepositFilterRef.current =\n tab === \"stables\" ? \"stablecoins\" : tab;\n },\n [activeMode, setSourcePickerDraftSelection]\n );\n\n const handleSourcePickerFilterTabSelect = useCallback(\n (tab: SourceFilterTab, scopedTokens?: SwapTokenOption[]) => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n\n const nextFilter: DepositSourceFilter =\n tab === \"stables\" ? \"stablecoins\" : tab;\n\n if (tab === \"custom\") {\n sourcePickerDraftDepositFilterRef.current = \"custom\";\n sourcePickerDraftTouchedRef.current = true;\n sourcePickerDraftModeRef.current = \"selected\";\n return;\n }\n if (scopedTokens) {\n handleSourcePickerDraftSelectionChange(scopedTokens, tab);\n return;\n }\n\n if (tab === \"all\") {\n sourcePickerDraftDepositFilterRef.current = nextFilter;\n sourcePickerDraftTouchedRef.current = false;\n sourcePickerDraftModeRef.current = \"all\";\n setSourcePickerDraftSelection(getAutoExactOutSourceTokensForPicker());\n return;\n }\n\n if (activeMode !== \"deposit\") return;\n\n const selection = getResolvedDepositSourceSelection({\n filter: nextFilter,\n isManualSelection: false,\n });\n const sourcePoolTokens = getDepositSourceTokensForIds(\n selection.sourcePoolIds\n );\n\n sourcePickerDraftDepositFilterRef.current = nextFilter;\n sourcePickerDraftTouchedRef.current = false;\n sourcePickerDraftModeRef.current = \"all\";\n setSourcePickerDraftSelection(sourcePoolTokens);\n },\n [\n activeMode,\n getAutoExactOutSourceTokensForPicker,\n handleSourcePickerDraftSelectionChange,\n getDepositSourceTokensForIds,\n getResolvedDepositSourceSelection,\n setSourcePickerDraftSelection,\n ]\n );\n\n const commitSourcePickerDraft = useCallback(\n (tokens?: SwapTokenOption[]) => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") {\n resetSourcePickerDraft();\n closeDrawerToIdle();\n return;\n }\n\n const nextTokens =\n tokens ?? sourcePickerDraftTokensRef.current ?? fromTokens;\n const normalizedTokens = nextTokens.map((token) => ({\n ...token,\n userAmount: \"\",\n }));\n\n setSourceSelectionTouched(sourcePickerDraftTouchedRef.current);\n setExactOutQuoteSourceModeValue(sourcePickerDraftModeRef.current);\n setDepositSourceFilter(sourcePickerDraftDepositFilterRef.current);\n invalidateExactOutQuoteForRefresh({\n sourceTokens: normalizedTokens,\n });\n setSourceSelectionRevision((current) => current + 1);\n setFromTokens(normalizedTokens);\n resetSourcePickerDraft();\n closeDrawerToIdle();\n },\n [\n activeMode,\n closeDrawerToIdle,\n fromTokens,\n invalidateExactOutQuoteForRefresh,\n resetSourcePickerDraft,\n setExactOutQuoteSourceModeValue,\n ]\n );\n\n const sourcePickerSelectedTokens =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n swapStep === \"choose-swap-asset\"\n ? (sourcePickerDraftTokens ?? fromTokens)\n : fromTokens;\n\n useEffect(() => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n if (lockedDestinationSourceTokens.length === 0) return;\n if (activeMode === \"deposit\" && !sourceSelectionTouched) return;\n\n setFromTokens((current) => {\n const missing = lockedDestinationSourceTokens.filter(\n (locked) =>\n !current.some(\n (token) =>\n getTokenSelectionKey(token) === getTokenSelectionKey(locked)\n )\n );\n if (missing.length === 0) return current;\n return [\n ...current,\n ...missing.map((token) => ({ ...token, userAmount: \"\" })),\n ];\n });\n }, [activeMode, lockedDestinationSourceTokens, sourceSelectionTouched]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (sourceSelectionTouched) return;\n if (\n !toToken ||\n !depositTokenAmountForQuote ||\n depositTokenAmountForQuote.lte(0)\n ) {\n return;\n }\n if (resolvedDepositSourceTokens.length === 0) {\n return;\n }\n\n setFromTokens((current) => {\n const canInitialize = current.length === 0;\n if (!canInitialize) return current;\n\n const next: SwapTokenOption[] = [];\n const seen = new Set();\n for (const token of resolvedDepositSourceTokens) {\n const key = getTokenSelectionKey(token);\n if (!key || seen.has(key)) continue;\n seen.add(key);\n next.push({ ...token, userAmount: \"\" });\n }\n\n const currentKeys = current.map(getTokenSelectionKey).sort().join(\"|\");\n const nextKeys = next.map(getTokenSelectionKey).sort().join(\"|\");\n if (currentKeys === nextKeys) return current;\n return next;\n });\n }, [\n activeMode,\n depositQuoteAmountKey,\n resolvedDepositSourceTokens,\n sourceSelectionTouched,\n toTokenQuoteKey,\n ]);\n\n // ---------------------------------------------------------------------------\n // Handlers\n // ---------------------------------------------------------------------------\n\n const applyConfiguredPrefillsAfterReset = () => {\n const prefillAmount = config.prefill?.amount ?? \"\";\n const prefillRecipient = config.prefill?.recipient ?? \"\";\n\n appliedTokenPrefillRef.current = null;\n syncingIntentSourcesRef.current = false;\n maxPercentRunRef.current += 1;\n setAmount(prefillAmount);\n setRecipientAddress(prefillRecipient);\n setTxError(null);\n setSwapQuoteIssue(null);\n setIntentToAmount(undefined);\n setIntentFeeUsd(undefined);\n setIntentData(null);\n setPredictiveQuote(null);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setMaxCalculationPercent(null);\n setSourceSelectionTouched(false);\n setDepositSourceFilter(\"all\");\n setExactOutQuoteSourceModeValue(\"all\");\n setSourceSelectionRevision((current) => current + 1);\n setDepositAmountMode(\"token\");\n\n if (activeMode === \"swap\") {\n const sourcePrefill = config.prefill?.source;\n const destinationPrefill = config.prefill?.destination;\n const sourceToken = resolvePrefillToken(sourcePrefill);\n const destinationToken = resolvePrefillToken(destinationPrefill);\n\n setFromTokens(\n sourceToken\n ? [\n {\n ...sourceToken,\n userAmount: prefillAmount,\n },\n ]\n : []\n );\n setSourceSelectionTouched(Boolean(sourceToken));\n setToToken(destinationToken);\n setSelectedOpportunity(undefined);\n setSwapType(\"exactIn\");\n\n if (\n (!sourcePrefill || sourceToken) &&\n (!destinationPrefill || destinationToken) &&\n (sourcePrefill || destinationPrefill)\n ) {\n appliedTokenPrefillRef.current = [\n sourcePrefill\n ? `source:${sourcePrefill.chain}:${sourcePrefill.token.toLowerCase()}`\n : \"\",\n destinationPrefill\n ? `destination:${destinationPrefill.chain}:${destinationPrefill.token.toLowerCase()}`\n : \"\",\n config.prefill?.amount ? `amount:${config.prefill.amount}` : \"\",\n ].join(\"|\");\n }\n return;\n }\n\n if (activeMode === \"send\") {\n const sendPrefill =\n config.prefill?.token && config.prefill?.chain\n ? {\n token: config.prefill.token,\n chain: config.prefill.chain,\n }\n : config.prefill?.destination;\n const token = resolvePrefillToken(sendPrefill);\n\n setFromTokens([]);\n setSelectedOpportunity(undefined);\n setToToken(token);\n setSwapType(\"exactOut\");\n\n if (sendPrefill && token) {\n appliedTokenPrefillRef.current = `send:${sendPrefill.chain}:${sendPrefill.token.toLowerCase()}`;\n }\n return;\n }\n\n const destinationPrefill = config.prefill?.destination;\n const configuredPrefillDeposit = destinationPrefill\n ? configuredDepositOptions.find(\n (deposit) =>\n deposit.chainId === destinationPrefill.chain &&\n deposit.tokenAddress.toLowerCase() ===\n destinationPrefill.token.toLowerCase()\n )\n : undefined;\n const nextDeposit = configuredPrefillDeposit ?? configuredDeposit;\n\n setFromTokens([]);\n setSelectedOpportunity(nextDeposit);\n setToToken(nextDeposit ? toTokenFromOpportunity(nextDeposit) : undefined);\n setSwapType(\"exactOut\");\n };\n\n const handleReset = () => {\n clearPendingSwapIntent();\n setSwapStep(\"idle\");\n setCurrentSwapId(null);\n currentSwapIdRef.current = null;\n currentSwapStartedAtRef.current = 0;\n amountEnteredLastValueRef.current = config.prefill?.amount ?? \"\";\n applyConfiguredPrefillsAfterReset();\n rotateAttempt();\n };\n\n const resetSourceSelectionAfterFailure = () => {\n lastAutoIntentSourceTokensRef.current = [];\n lastIntentSourceTokensRef.current = [];\n resetSourcePickerDraft();\n resetExactOutSourcesToAuto();\n };\n\n const handleFailureBack = () => {\n clearPendingSwapIntent();\n resetSourceSelectionAfterFailure();\n setTxError(null);\n void refreshSelectedSourceBalances();\n setSwapStep(\"idle\");\n setCurrentSwapId(null);\n currentSwapIdRef.current = null;\n currentSwapStartedAtRef.current = 0;\n rotateAttempt();\n };\n\n const clearTerminalInputState = () => {\n setAmount(\"\");\n setRecipientAddress(\"\");\n setTxError(null);\n setSwapQuoteIssue(null);\n setIntentToAmount(undefined);\n setIntentFeeUsd(undefined);\n setIntentData(null);\n setFromTokens((current) => (current.length === 0 ? current : []));\n setSourceSelectionTouched(false);\n setDepositSourceFilter(\"all\");\n setDepositAmountMode(\"token\");\n };\n\n const resetInputsAfterSuccessfulExecution = () => {\n clearTerminalInputState();\n if (activeMode === \"deposit\") {\n setSelectedOpportunity(configuredDeposit);\n setToToken(\n configuredDeposit\n ? toTokenFromOpportunity(configuredDeposit)\n : undefined\n );\n } else {\n setToToken(undefined);\n }\n };\n\n const handleTerminalReceiptDone = () => {\n clearPendingSwapIntent();\n clearTerminalInputState();\n void refreshSelectedSourceBalances();\n setSwapStep(\"idle\");\n setCurrentSwapId(null);\n currentSwapIdRef.current = null;\n currentSwapStartedAtRef.current = 0;\n amountEnteredLastValueRef.current = \"\";\n rotateAttempt();\n };\n\n const handleModalOpenChange = useCallback(\n (open: boolean) => {\n if (!open && swapStepRef.current === \"progress\") return;\n if (!isControlledOpen) {\n setInternalOpen(open);\n }\n onOpenChange?.(open);\n if (!open) {\n clearPendingSwapIntent();\n onClose?.();\n }\n },\n [clearPendingSwapIntent, isControlledOpen, onClose, onOpenChange]\n );\n\n const handleClose = () => {\n if (!embed) {\n handleModalOpenChange(false);\n return;\n }\n clearPendingSwapIntent();\n onClose?.();\n };\n\n const handleConnectWallet = async () => {\n if (walletActionPending || nexusLoading) return;\n\n const clickHandler = onConnectClick || onConnectWallet;\n if (clickHandler) {\n setWalletActionPending(true);\n setTxError(null);\n try {\n await clickHandler();\n } catch (error: any) {\n setTxError(error?.message || \"Unable to connect wallet.\");\n } finally {\n setWalletActionPending(false);\n }\n return;\n }\n\n if (isWalletConnectPending) return;\n\n setWalletActionPending(true);\n setTxError(null);\n try {\n let activeConnector = connector;\n\n if (walletStatus !== \"connected\") {\n const nextConnector = connectors[0];\n if (!nextConnector) {\n throw new Error(\"No wallet connector available.\");\n }\n await connectAsync({ connector: nextConnector });\n return;\n }\n\n const effectiveProvider = await getEffectiveWalletProvider(\n activeConnector\n );\n\n if (\n !effectiveProvider ||\n typeof effectiveProvider.request !== \"function\"\n ) {\n throw new Error(\"Wallet provider is not ready yet.\");\n }\n\n await handleInit(effectiveProvider as EthereumProvider, ownerAddress);\n } catch (error: any) {\n setTxError(error?.message || \"Unable to connect wallet.\");\n } finally {\n setWalletActionPending(false);\n }\n };\n\n const handleOpenRecipientEditor = () => {\n if (activeMode === \"swap\" && !recipientAddress && defaultRecipientAddress) {\n setRecipientAddress(defaultRecipientAddress);\n }\n setTxError(null);\n openDrawerStep(\"enter-recipient\");\n };\n\n const handleResetRecipientToDefault = () => {\n setRecipientAddress(defaultRecipientAddress);\n setTxError(null);\n };\n\n const handleSaveRecipient = () => {\n const next = recipientAddress.trim();\n if (!next) {\n setTxError(\"Recipient address is required\");\n return;\n }\n if (!next.endsWith(\".eth\") && !isAddress(next)) {\n setTxError(\"Incorrect address\");\n return;\n }\n if (\n activeMode === \"send\" &&\n ownerAddress &&\n isAddress(next) &&\n next.toLowerCase() === ownerAddress.toLowerCase()\n ) {\n setTxError(\"Recipient cannot be the connected wallet.\");\n return;\n }\n setRecipientAddress(next);\n setTxError(null);\n closeDrawerToIdle();\n };\n\n /** Start swap flow — v2 SDK per-operation onIntent hooks populate preview. */\n const handleEnterPreview = async (options: { background?: boolean } = {}) => {\n const { background = false } = options;\n const isExactOutFlow = activeMode === \"deposit\" || activeMode === \"send\";\n const quoteInputKey = activeQuoteInputKeyRef.current;\n const isCurrentQuoteInput = () =>\n activeQuoteInputKeyRef.current === quoteInputKey;\n\n if (!toToken) {\n return;\n }\n\n if (isExactOutFlow) {\n if (!hasPositiveDecimalInput(amount)) {\n return;\n }\n } else if (!hasReadyExactInSwapInput(fromTokens, toToken)) {\n if (!background) {\n setTxError(null);\n setSwapQuoteIssue(null);\n }\n return;\n }\n\n const receiveIssue = buildReceiveAmountIssue();\n if (receiveIssue) {\n applyReceiveAmountIssue(receiveIssue);\n if (!background && swapStepRef.current !== \"idle\") {\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n }\n return;\n }\n\n const configuredIssue = buildConfiguredAmountIssue();\n if (configuredIssue) {\n clearPreviewForBlockingAmountIssue();\n if (!background && swapStepRef.current !== \"idle\") {\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n }\n return;\n }\n\n const sourceBalanceIssue = isExactOutFlow\n ? buildExactOutSourceBalanceIssue()\n : null;\n if (sourceBalanceIssue) {\n clearPreviewForBlockingAmountIssue();\n setSwapQuoteIssue(sourceBalanceIssue);\n if (!background && swapStepRef.current !== \"idle\") {\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n }\n return;\n }\n\n if (!background && activeMode === \"deposit\") {\n trackDeposit(\"deposit_confirm_clicked\", {\n amountToken: depositTokenDisplay,\n amountUsd: Number(depositUsdDisplay) || 0,\n selectionMode: sourceSelectionTouched ? \"manual\" : \"auto\",\n sourceCount: (intentData?.sources ?? []).length,\n });\n }\n\n setTxError(null);\n setSwapQuoteIssue(null);\n\n if (\n !background &&\n swapIntentRef.current?.runId === swapRunIdRef.current &&\n swapIntentRef.current?.quoteInputKey === quoteInputKey &&\n intentData &&\n (activeMode !== \"send\" || Boolean(recipientAddress)) &&\n ((activeMode !== \"deposit\" && activeMode !== \"send\") ||\n (intentData.sources ?? []).length > 0 ||\n Boolean(intentData.destination))\n ) {\n swapStepRef.current = \"preview-intent\";\n setSwapStep(\"preview-intent\");\n return;\n }\n\n let resolvedRecipientAddress =\n activeMode === \"swap\" ? effectiveRecipientAddress : recipientAddress;\n\n if (!background && activeMode === \"send\" && !resolvedRecipientAddress) {\n setTxError(\"Recipient address is required\");\n return;\n }\n\n if ((!background && activeMode === \"send\") || hasCustomSwapRecipient) {\n if (!resolvedRecipientAddress) {\n setTxError(\"Recipient address is required\");\n return;\n }\n\n if (\n activeMode === \"send\" &&\n ownerAddress &&\n isAddress(resolvedRecipientAddress) &&\n resolvedRecipientAddress.toLowerCase() === ownerAddress.toLowerCase()\n ) {\n setTxError(\"Recipient cannot be the connected wallet.\");\n return;\n }\n\n if (resolvedRecipientAddress.endsWith(\".eth\")) {\n try {\n const mainnetClient =\n publicClient?.chain?.id === 1\n ? publicClient\n : createPublicClient({\n chain: mainnet,\n transport: http(),\n });\n const ensAddr = await mainnetClient.getEnsAddress({\n name: normalize(resolvedRecipientAddress),\n });\n if (!ensAddr) {\n setTxError(\"Could not resolve ENS name to an address.\");\n return;\n }\n resolvedRecipientAddress = ensAddr;\n } catch (e: any) {\n setTxError(e.message || \"Failed to resolve ENS name.\");\n return;\n }\n } else {\n if (!isAddress(resolvedRecipientAddress)) {\n setTxError(\"Invalid recipient address.\");\n return;\n }\n }\n\n if (\n activeMode === \"send\" &&\n ownerAddress &&\n isAddress(resolvedRecipientAddress) &&\n resolvedRecipientAddress.toLowerCase() === ownerAddress.toLowerCase()\n ) {\n setTxError(\"Recipient cannot be the connected wallet.\");\n return;\n }\n }\n\n if (!isCurrentQuoteInput()) {\n return;\n }\n\n if (!background) {\n swapStepRef.current = \"preview-intent\";\n setSwapStep(\"preview-intent\");\n }\n setIntentLoading(true);\n setQuoteRefreshing(background);\n setIntentToAmount(undefined);\n setIntentFeeUsd(undefined);\n setIntentData(null);\n swapIntentRef.current?.deny();\n swapIntentRef.current = null;\n if (!background) {\n resetProgressEvents();\n swapStepsListRef.current = [];\n resetSteps();\n }\n\n if (!nexusSDK) {\n setTxError(\"SDK not initialized\");\n if (!background) {\n setSwapStep(\"idle\");\n }\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n swapRunIdRef.current += 1;\n const runId = swapRunIdRef.current;\n\n const isActionPlanStep = (step: SwapStepType | BridgeStepType) => {\n const type = getProgressStepType(step);\n return (\n type === \"APPROVAL\" ||\n type === \"TRANSACTION_SENT\" ||\n type === \"TRANSACTION_CONFIRMED\"\n );\n };\n\n const hasSwapPlanSteps = (stepList: Array) =>\n stepList.some((step) => !isActionPlanStep(step));\n\n const handleProgressStepSideEffects = (\n event: any,\n step: SwapStepType | BridgeStepType,\n completed: boolean\n ) => {\n const type = getProgressStepType(step);\n const rawStepType = String(\n event?.stepType ?? (step as any)?.type ?? (step as any)?.typeID ?? \"\"\n ).toLowerCase();\n const rawState = String(event?.state ?? \"\").toLowerCase();\n const explorerUrl = getPlanStepExplorerUrl(event, step);\n const sourceMovementStep = isSourceMovementProgressStep(type, rawStepType);\n const hasSourceMovementTransaction = Boolean(\n explorerUrl || getPlanStepTransactionHash(event, step)\n );\n const intentExplorerUrl = getEventIntentExplorerUrl(\n appConfig.nexusNetwork,\n event,\n step\n );\n\n patchCurrentIntentExplorerUrl(intentExplorerUrl);\n\n if (\n type === \"TRANSACTION_SENT\" ||\n type === \"TRANSACTION_CONFIRMED\" ||\n type === \"SOURCE_SWAP\" ||\n type === \"BRIDGE_DEPOSIT\" ||\n type === \"BRIDGE_INTENT_SUBMISSION\" ||\n type === \"BRIDGE_FILL\" ||\n type === \"DESTINATION_SWAP\" ||\n type === \"SWAP_COMPLETE\" ||\n type === \"SWAP_SKIPPED\"\n ) {\n markSwapExecutionStarted();\n }\n\n if (\n sourceMovementStep &&\n hasSourceMovementTransaction &&\n PLAN_STEP_FUNDS_MAY_HAVE_MOVED_STATES.has(rawState)\n ) {\n fundsMovedRef.current = true;\n }\n\n if (explorerUrl) {\n if (\n rawStepType === \"destination_swap\" ||\n rawStepType === \"execute_transaction\" ||\n type.includes(\"DESTINATION_SWAP\") ||\n type === \"TRANSACTION_SENT\" ||\n type === \"TRANSACTION_CONFIRMED\"\n ) {\n mergeExplorerUrls({ destinationExplorerUrl: explorerUrl });\n } else if (\n sourceMovementStep\n ) {\n mergeExplorerUrls({ sourceExplorerUrl: explorerUrl });\n }\n\n if (\n !intentUrlRef.current &&\n (rawStepType === \"bridge_intent_submission\" ||\n rawStepType === \"request_submission\" ||\n type === \"BRIDGE_INTENT_SUBMISSION\")\n ) {\n patchCurrentIntentExplorerUrl(explorerUrl);\n }\n }\n\n if (completed) {\n onStepComplete(step as SwapStepType);\n }\n };\n\n const handlePlanEvent = (event: any) => {\n if (event.type === \"plan_preview\" || event.type === \"plan_confirmed\") {\n const stepList = Array.isArray(event.plan?.steps)\n ? event.plan.steps.map((step: any) =>\n normalizePlanStep(step, step?.type, undefined, false)\n )\n : [];\n logSwapPlanSteps(event.type, stepList, event.plan?.steps);\n if (stepList.length === 0) return;\n\n if (hasSwapPlanSteps(stepList)) {\n swapStepsListRef.current = stepList as SwapStepType[];\n appendProgressListEvent(\n PROGRESS_EVENT_NAMES.SWAP_PLAN_LIST,\n stepList\n );\n } else {\n appendProgressListEvent(\n PROGRESS_EVENT_NAMES.BRIDGE_PLAN_LIST,\n stepList\n );\n }\n onStepsList(stepList as SwapStepType[]);\n return;\n }\n\n if (event.type !== \"plan_progress\") {\n logSdkSwapEvent(\"unhandled typed event\", event);\n return;\n }\n\n const state = String(event.state ?? \"\").toLowerCase();\n const completed = PLAN_FINAL_STATES.has(state);\n const step = normalizePlanStep(\n event.step,\n event.stepType,\n event.state,\n completed\n );\n const eventName = isActionPlanStep(step)\n ? PROGRESS_EVENT_NAMES.BRIDGE_PLAN_PROGRESS\n : PROGRESS_EVENT_NAMES.SWAP_PLAN_PROGRESS;\n\n logSwapPlanProgress(event, step, eventName, completed);\n appendProgressEvent(eventName, step, completed, event);\n handleProgressStepSideEffects(event, step, completed);\n };\n\n const appendSkippedSwapProgress = () => {\n const step = {\n completed: true,\n type: \"SWAP_SKIPPED\",\n typeID: \"SWAP_SKIPPED\",\n } as SwapStepType;\n enterSkippedSwapProgress();\n appendProgressEvent(PROGRESS_EVENT_NAMES.SWAP_PLAN_PROGRESS, step, true);\n onStepComplete(step);\n };\n\n const handleSwapEvent = (event: any) => {\n if (!event || typeof event !== \"object\") return;\n if (typeof event.type === \"string\") {\n handlePlanEvent(event);\n return;\n }\n logSdkSwapEvent(\"ignored event without string type\", event);\n };\n\n const onEvent = (event: any) => {\n const isCurrentRun = swapRunIdRef.current === runId;\n const isCurrentQuote = isCurrentQuoteInput();\n logSdkSwapEvent(\"onEvent\", event, {\n currentRunId: swapRunIdRef.current,\n isCurrentQuote,\n isCurrentRun,\n quoteInputKey,\n runId,\n });\n if (!isCurrentRun || !isCurrentQuote) {\n logSdkSwapEvent(\"ignored stale onEvent\", event, {\n currentRunId: swapRunIdRef.current,\n isCurrentQuote,\n quoteInputKey,\n runId,\n });\n return;\n }\n patchCurrentIntentExplorerUrl(\n getEventIntentExplorerUrl(appConfig.nexusNetwork, event)\n );\n handleSwapEvent(event);\n };\n\n const buildRecipientTransferExecuteConfig = (transferAmount: bigint) => {\n if (!resolvedRecipientAddress) {\n throw new Error(\"Recipient address is required\");\n }\n\n const isNative =\n !toToken.contractAddress ||\n toToken.contractAddress.toLowerCase() ===\n \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\" ||\n toToken.contractAddress ===\n \"0x0000000000000000000000000000000000000000\";\n\n if (isNative) {\n return {\n to: resolvedRecipientAddress as `0x${string}`,\n value: transferAmount,\n gas: BigInt(100000),\n };\n }\n\n return {\n to: toToken.contractAddress as `0x${string}`,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"transfer\",\n args: [resolvedRecipientAddress as `0x${string}`, transferAmount],\n }),\n gas: BigInt(100000),\n };\n };\n\n const executeRecipientTransfer = async (transferAmount: bigint) => {\n const result = await nexusSDK.execute(\n {\n toChainId: toToken.chainId!,\n ...buildRecipientTransferExecuteConfig(transferAmount),\n },\n { onEvent }\n );\n const finalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n getSdkTransactionHash(result),\n result\n );\n if (finalExplorerUrl) {\n setTransferExplorerUrl(finalExplorerUrl);\n mergeExplorerUrls({ destinationExplorerUrl: finalExplorerUrl });\n }\n return finalExplorerUrl;\n };\n\n try {\n if (!isExactOutFlow) {\n const fromPayload: {\n chainId: number;\n tokenAddress: `0x${string}`;\n amountRaw: bigint;\n }[] = [];\n\n const exactInSourceTokens = getReadyExactInSourceTokens(fromTokens);\n\n for (const token of exactInSourceTokens) {\n // Determine the amount to use for this specific token\n let rawAmountStr = token.userAmount;\n if (!rawAmountStr && exactInSourceTokens.length === 1) {\n rawAmountStr = amount; // fallback for single-token case\n }\n\n let cleanAmount = parseFiatNumber(rawAmountStr) ?? new Decimal(0);\n if (cleanAmount.lte(0)) continue;\n\n if (token.userAmountMode === \"usd\") {\n const tokenBalance =\n parseFiatNumber(token.balance) ?? new Decimal(0);\n const fiatBalance =\n parseFiatNumber(token.balanceInFiat) ?? new Decimal(0);\n const price = tokenBalance.gt(0)\n ? fiatBalance.div(tokenBalance)\n : new Decimal(0);\n if (price.gt(0)) {\n cleanAmount = cleanAmount.div(price);\n } else {\n cleanAmount = new Decimal(0);\n }\n }\n\n if (cleanAmount.lte(0)) continue;\n\n const safeTokenAmountStr = toViemDecimalString(\n cleanAmount,\n token.decimals || 18\n );\n\n fromPayload.push({\n chainId: token.chainId!,\n tokenAddress: token.contractAddress as `0x${string}`,\n amountRaw: parseUnits(safeTokenAmountStr, token.decimals || 18),\n });\n }\n\n if (fromPayload.length === 0) {\n throw new Error(\"No source amount available for swap.\");\n }\n\n resetExplorerUrls();\n const exactInSwapPayload = {\n sources: fromPayload,\n toChainId: toToken.chainId!,\n toTokenAddress: toToken.contractAddress as `0x${string}`,\n };\n let intentExplorerUrl: string | null = null;\n let intentId = currentSwapEntry?.intentId;\n let finalExplorerUrl: string | null =\n explorerUrlsRef.current.destinationExplorerUrl ||\n explorerUrlsRef.current.sourceExplorerUrl;\n\n if (hasCustomSwapRecipient && resolvedRecipientAddress) {\n const sdkWithOptionalTransfer = nexusSDK as any;\n\n if (typeof sdkWithOptionalTransfer.swapAndTransfer === \"function\") {\n const swapAndTransferExactInInput = {\n mode: \"exactIn\",\n recipient: resolvedRecipientAddress as `0x${string}`,\n ...exactInSwapPayload,\n };\n logSdkIntentInput(\"swapAndTransfer exactIn\", swapAndTransferExactInInput, {\n activeMode,\n quoteInputKey,\n runId,\n });\n const result = await sdkWithOptionalTransfer.swapAndTransfer(\n swapAndTransferExactInInput,\n { onEvent }\n );\n if (result?.success === false) {\n throw new Error(result?.error || \"Swap and transfer failed\");\n }\n\n const swapResult = getSdkSwapResult(result);\n intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result,\n swapResult\n );\n intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n const resultFinalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n getSdkTransactionHash(result),\n result,\n swapResult\n );\n finalExplorerUrl = resultFinalExplorerUrl || finalExplorerUrl;\n if (resultFinalExplorerUrl) {\n setTransferExplorerUrl(resultFinalExplorerUrl);\n mergeExplorerUrls({\n destinationExplorerUrl: resultFinalExplorerUrl,\n });\n }\n } else {\n logSdkIntentInput(\"swapWithExactIn\", exactInSwapPayload, {\n activeMode,\n quoteInputKey,\n runId,\n });\n startIntentFetchTiming({\n background,\n operation: \"swapWithExactIn\",\n quoteInputKey,\n runId,\n });\n const result = await nexusSDK.swapWithExactIn(exactInSwapPayload, {\n hooks: {\n onIntent: (data) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n },\n onEvent,\n });\n\n intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result\n );\n intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n\n const latestSwapIntent = (\n swapIntentRef.current as unknown as {\n intent?: SwapIntentData;\n } | null\n )?.intent;\n const transferAmount = latestSwapIntent?.destination?.amount;\n if (!transferAmount) {\n throw new Error(\n \"Unable to determine received amount to transfer.\"\n );\n }\n\n const transferAmountBigInt = parseUnits(\n toViemDecimalString(transferAmount, toToken.decimals || 18),\n toToken.decimals || 18\n );\n finalExplorerUrl =\n (await executeRecipientTransfer(transferAmountBigInt)) ||\n finalExplorerUrl;\n }\n } else {\n // Start exact-in swap — the intent hook will fire and populate preview\n logSdkIntentInput(\"swapWithExactIn\", exactInSwapPayload, {\n activeMode,\n quoteInputKey,\n runId,\n });\n startIntentFetchTiming({\n background,\n operation: \"swapWithExactIn\",\n quoteInputKey,\n runId,\n });\n const result = await nexusSDK.swapWithExactIn(exactInSwapPayload, {\n hooks: {\n onIntent: (data) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n },\n onEvent,\n });\n intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result\n );\n intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n const swapResult = getSdkSwapResult(result);\n const resultFinalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n getSdkTransactionHash(result),\n result,\n swapResult\n );\n finalExplorerUrl = resultFinalExplorerUrl || finalExplorerUrl;\n if (resultFinalExplorerUrl) {\n setTransferExplorerUrl(resultFinalExplorerUrl);\n mergeExplorerUrls({\n destinationExplorerUrl: resultFinalExplorerUrl,\n });\n }\n }\n\n if (\n swapRunIdRef.current === runId &&\n swapStepRef.current === \"progress\"\n ) {\n const resolvedFinalExplorerUrl =\n finalExplorerUrl ||\n explorerUrlsRef.current.destinationExplorerUrl ||\n explorerUrlsRef.current.sourceExplorerUrl;\n const resolvedIntentExplorerUrl =\n intentExplorerUrl || intentUrlRef.current;\n finishCurrentSwapHistoryEntry(\"fulfilled\", {\n finalExplorerUrl: resolvedFinalExplorerUrl,\n ...(resolvedIntentExplorerUrl\n ? { intentExplorerUrl: resolvedIntentExplorerUrl }\n : {}),\n ...(intentId ? { intentId } : {}),\n });\n resetInputsAfterSuccessfulExecution();\n onComplete?.();\n setSwapStep(\"success\");\n }\n } else {\n const exactOutAmountString =\n activeMode === \"deposit\"\n ? depositTokenAmountForQuote\n ?.toDecimalPlaces(toToken.decimals || 18, Decimal.ROUND_DOWN)\n .toFixed()\n : amount;\n if (!exactOutAmountString || new Decimal(exactOutAmountString).lte(0)) {\n setTxError(\n depositAmountMode === \"usd\"\n ? \"Unable to convert USD amount into the destination token amount.\"\n : \"Enter a valid amount.\"\n );\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n const amountBigInt = parseUnits(\n toViemDecimalString(exactOutAmountString, toToken.decimals || 18),\n toToken.decimals || 18\n );\n\n resetExplorerUrls();\n\n const fromSourcesPayload = buildExactOutSourcesPayload(\n getExactOutSourceTokens()\n );\n\n let executeConfig: any;\n if (activeMode === \"deposit\" && !selectedOpportunity?.executeDeposit) {\n throw new Error(\"Deposit config is missing executeDeposit.\");\n }\n\n if (activeMode === \"deposit\" && selectedOpportunity) {\n const user = (ownerAddress ?? connectedAddress) as `0x${string}`;\n\n const executeParams = selectedOpportunity.executeDeposit(\n selectedOpportunity.tokenSymbol,\n selectedOpportunity.tokenAddress,\n amountBigInt,\n selectedOpportunity.chainId,\n user\n );\n if (!isPositiveGasLimit(executeParams.gas)) {\n throw new Error(\n \"Deposit config executeDeposit must return a positive gas limit.\"\n );\n }\n executeConfig = {\n to: executeParams.to,\n value: executeParams.value,\n data: executeParams.data,\n tokenApproval: executeParams.tokenApproval,\n gas: executeParams.gas,\n };\n } else if (\n (activeMode === \"send\" || hasCustomSwapRecipient) &&\n resolvedRecipientAddress\n ) {\n executeConfig = buildRecipientTransferExecuteConfig(amountBigInt);\n }\n\n if (executeConfig?.tokenApproval) {\n executeConfig = {\n ...executeConfig,\n tokenApproval: {\n toTokenAddress:\n executeConfig.tokenApproval.toTokenAddress ||\n toToken.contractAddress,\n amount: executeConfig.tokenApproval.amount,\n spender: executeConfig.tokenApproval.spender,\n },\n };\n }\n\n if (executeConfig) {\n const sdkWithOptionalTransfer = nexusSDK as any;\n const isTransferExactOut =\n (activeMode === \"send\" || hasCustomSwapRecipient) &&\n typeof sdkWithOptionalTransfer.swapAndTransfer === \"function\";\n const exactOutOperationInput = isTransferExactOut\n ? {\n mode: \"exactOut\",\n toChainId: toToken.chainId!,\n toTokenAddress: toToken.contractAddress as `0x${string}`,\n toAmountRaw: amountBigInt,\n recipient: resolvedRecipientAddress as `0x${string}`,\n ...fromSourcesPayload,\n }\n : {\n toChainId: toToken.chainId!,\n toTokenAddress: toToken.contractAddress as `0x${string}`,\n toAmountRaw: amountBigInt,\n execute: executeConfig,\n ...fromSourcesPayload,\n };\n logSdkIntentInput(\n isTransferExactOut\n ? \"swapAndTransfer exactOut\"\n : \"swapAndExecute exactOut\",\n exactOutOperationInput,\n {\n activeMode,\n quoteInputKey,\n runId,\n }\n );\n startIntentFetchTiming({\n background,\n operation: isTransferExactOut\n ? \"swapAndTransfer exactOut\"\n : \"swapAndExecute exactOut\",\n quoteInputKey,\n runId,\n });\n const result =\n isTransferExactOut\n ? await sdkWithOptionalTransfer.swapAndTransfer(\n exactOutOperationInput,\n {\n onEvent,\n onIntent: (data: any) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n }\n )\n : await nexusSDK.swapAndExecute(\n exactOutOperationInput as any,\n {\n onEvent,\n onIntent: (data) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n }\n );\n\n const swapResult = result?.swapResult ?? result?.result ?? null;\n const swapSkipped = Boolean((result as any)?.swapSkipped);\n if (swapSkipped) {\n appendSkippedSwapProgress();\n }\n if (\n !swapResult &&\n !swapSkipped &&\n activeMode !== \"send\" &&\n !hasCustomSwapRecipient\n ) {\n throw new Error(\"Swap failed\");\n }\n const executeTxHash = getSdkTransactionHash(result);\n const intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result,\n swapResult\n );\n const intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n const finalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n executeTxHash,\n result,\n swapResult\n );\n if (finalExplorerUrl) {\n if (activeMode === \"send\" || hasCustomSwapRecipient) {\n setTransferExplorerUrl(finalExplorerUrl);\n }\n mergeExplorerUrls({ destinationExplorerUrl: finalExplorerUrl });\n }\n patchCurrentSwapHistoryEntry({\n ...(finalExplorerUrl ? { finalExplorerUrl } : {}),\n ...(intentExplorerUrl ? { intentExplorerUrl } : {}),\n ...(intentId ? { intentId } : {}),\n });\n } else {\n const exactOutSwapInput = {\n toChainId: toToken.chainId!,\n toTokenAddress: toToken.contractAddress as `0x${string}`,\n toAmountRaw: amountBigInt,\n ...fromSourcesPayload,\n };\n logSdkIntentInput(\"swapWithExactOut\", exactOutSwapInput, {\n activeMode,\n quoteInputKey,\n runId,\n });\n startIntentFetchTiming({\n background,\n operation: \"swapWithExactOut\",\n quoteInputKey,\n runId,\n });\n const result = await nexusSDK.swapWithExactOut(\n exactOutSwapInput,\n {\n hooks: {\n onIntent: (data) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n },\n onEvent,\n }\n );\n const intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result\n );\n const intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n const swapResult = getSdkSwapResult(result);\n const finalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n getSdkTransactionHash(result),\n result,\n swapResult\n );\n if (finalExplorerUrl) {\n mergeExplorerUrls({ destinationExplorerUrl: finalExplorerUrl });\n }\n patchCurrentSwapHistoryEntry({\n ...(finalExplorerUrl ? { finalExplorerUrl } : {}),\n ...(intentExplorerUrl ? { intentExplorerUrl } : {}),\n ...(intentId ? { intentId } : {}),\n });\n }\n\n if (\n swapRunIdRef.current === runId &&\n swapStepRef.current === \"progress\"\n ) {\n finishCurrentSwapHistoryEntry(\"fulfilled\");\n resetInputsAfterSuccessfulExecution();\n onComplete?.();\n if (activeMode === \"deposit\") {\n reachedTerminalRef.current = true;\n const now = Date.now();\n trackDeposit(\"deposit_completed\", {\n postConfirmDurationMs: previewConfirmedTsRef.current\n ? now - previewConfirmedTsRef.current\n : 0,\n totalDurationMs: now - widgetOpenedTsRef.current,\n attemptCount: attemptCountRef.current,\n amountToken: depositTokenDisplay,\n amountUsd: Number(depositUsdDisplay) || 0,\n });\n }\n setSwapStep(\"success\");\n }\n }\n } catch (err: any) {\n const caughtTimeout = isTimeoutLikeError(err);\n if (caughtTimeout) {\n console.warn(\"Timeout in handleEnterPreview:\", err);\n } else {\n console.error(\"Error in handleEnterPreview:\", err);\n }\n if (swapRunIdRef.current !== runId || !isCurrentQuoteInput()) {\n return;\n }\n finishIntentFetchTiming(runId, \"failed\");\n if (activeMode === \"deposit\" && err?.code !== \"USER_DENIED_INTENT\") {\n const hasActiveExecution =\n swapStepRef.current === \"progress\" &&\n Boolean(currentSwapIdRef.current);\n const isInsufficient = isInsufficientSourcesError(err);\n const errMessage =\n (typeof err?.message === \"string\" ? err.message : \"\") ||\n (typeof err === \"string\" ? err : \"\");\n const errName = typeof err?.name === \"string\" ? err.name : \"\";\n const isTimeout = isTimeoutLikeError(err);\n const isUserRejected =\n err?.code === 4001 ||\n err?.code === \"ACTION_REJECTED\" ||\n errName === \"UserRejectedRequestError\" ||\n /user rejected|user denied/i.test(errMessage);\n const failedAtStep:\n | \"simulation\"\n | \"nexus_operation\"\n | \"execute_leg\"\n | \"unknown\" = !hasActiveExecution ? \"simulation\" : \"nexus_operation\";\n const errorCategory: string = isUserRejected\n ? \"user_rejected\"\n : isTimeout\n ? \"timeout\"\n : isInsufficient\n ? \"no_eligible_sources\"\n : !hasActiveExecution\n ? \"quote_failed\"\n : fundsMovedRef.current\n ? \"pending_after_funds_moved\"\n : \"execution_failed\";\n reachedTerminalRef.current = true;\n if (fundsMovedRef.current) {\n trackDeposit(\"deposit_pending_after_funds_moved\", {\n errorCode: err?.code ?? \"UNKNOWN\",\n errorMessage: errMessage || \"Transaction pending.\",\n intentUrl: intentUrlRef.current,\n failedAtStep,\n });\n } else {\n trackDeposit(\"deposit_failed\", {\n errorCode: err?.code ?? \"UNKNOWN\",\n errorCategory,\n errorMessage: errMessage || \"Transaction failed.\",\n failedAtStep,\n });\n }\n }\n setQuoteRefreshing(false);\n setIntentLoading(false);\n setReceiveMaxCalculating(false);\n const hasActiveExecution =\n swapStepRef.current === \"progress\" && Boolean(currentSwapIdRef.current);\n const isTimeout = caughtTimeout;\n const showFailedProgressThenReceipt = (\n error: string,\n patch: Partial = {}\n ) => {\n const failedProgressEvent = progressEventsRef.current.at(-1);\n const isTransferExecution =\n activeMode === \"send\" || hasCustomSwapRecipient;\n const fallbackFailedStep =\n activeMode === \"deposit\" || isTransferExecution\n ? ({ type: \"APPROVAL\", typeID: \"AP\" } as BridgeStepType)\n : ({\n type: \"DETERMINING_SWAP\",\n typeID: \"DETERMINING_SWAP\",\n } as unknown as SwapStepType);\n const failedStep = failedProgressEvent?.step ?? fallbackFailedStep;\n const autoRefundAvailable =\n isAutoRefundAvailableProgressEvent(failedProgressEvent);\n setFailedProgressStep(failedStep);\n finishCurrentSwapHistoryEntry(\"failed\", {\n error,\n autoRefundAvailable,\n failureDescription: getFailureDescriptionForProgressStep(\n failedStep,\n autoRefundAvailable\n ),\n failureMessage: getFailureMessageForProgressStep(\n failedStep,\n hasCustomSwapRecipient ? \"send\" : activeMode,\n autoRefundAvailable\n ),\n failedStepType: getProgressStepType(failedStep),\n ...patch,\n });\n window.setTimeout(() => {\n if (\n swapRunIdRef.current === runId &&\n swapStepRef.current === \"progress\"\n ) {\n setSwapStep(\"failed\");\n }\n }, 700);\n };\n const showTimeoutReceipt = (\n message = \"Transaction timed out\",\n patch: Partial = {}\n ) => {\n finishCurrentSwapHistoryEntry(\"timeout\", {\n error: message,\n failureDescription:\n \"This transaction is still pending. Check the intent explorer for the latest status.\",\n failureMessage: TIMEOUT_LABEL,\n ...patch,\n });\n window.setTimeout(() => {\n if (\n swapRunIdRef.current === runId &&\n swapStepRef.current === \"progress\"\n ) {\n setSwapStep(\"failed\");\n }\n }, 700);\n };\n if (err?.code === \"USER_DENIED_INTENT\") {\n if (hasActiveExecution) {\n showFailedProgressThenReceipt(\"Transaction cancelled by user\");\n } else if (!background && swapStepRef.current === \"preview-intent\") {\n setSwapStep(\"idle\");\n }\n return;\n }\n if (isInsufficientSourcesError(err) && !hasActiveExecution) {\n const issue = buildInsufficientSourcesIssue(err);\n if (!background || swapStepRef.current === \"preview-intent\") {\n setSwapStep(\"idle\");\n }\n setTxError(null);\n setSwapQuoteIssue(issue);\n onError?.(issue.message);\n return;\n }\n if (isExactOutFlow && isViemInvalidDecimalError(err) && !hasActiveExecution) {\n const issue = buildExactOutSourceBalanceIssue();\n if (issue) {\n if (!background || swapStepRef.current === \"preview-intent\") {\n setSwapStep(\"idle\");\n }\n setTxError(null);\n setSwapQuoteIssue(issue);\n onError?.(issue.message);\n return;\n }\n }\n const errorMessage =\n err?.message ||\n (typeof err === \"string\"\n ? err\n : \"Transaction failed. Please try again or check console.\");\n if (isTimeout && hasActiveExecution) {\n showTimeoutReceipt(errorMessage);\n setTxError(null);\n return;\n }\n if (hasActiveExecution && fundsMovedRef.current) {\n showTimeoutReceipt(errorMessage, {\n failureDescription:\n \"Funds have already moved and the transaction is still pending. Check the intent explorer for the latest status.\",\n });\n setTxError(null);\n return;\n }\n if (hasActiveExecution) {\n showFailedProgressThenReceipt(errorMessage);\n } else if (!background || swapStepRef.current === \"preview-intent\") {\n setSwapStep(\"idle\");\n }\n setTxError(errorMessage);\n onError?.(errorMessage);\n }\n };\n\n const hasInsufficientSourcesQuoteIssue =\n swapQuoteIssue?.type === \"insufficientSources\";\n const hasReceiveAmountQuoteIssue = Boolean(receiveAmountIssue);\n\n useEffect(() => {\n if (activeMode !== \"swap\" || swapStep !== \"idle\" || !nexusSDK) return;\n\n if (syncingIntentSourcesRef.current) {\n syncingIntentSourcesRef.current = false;\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n }\n\n if (hasReceiveAmountQuoteIssue) {\n clearPendingSwapIntent(true);\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n if (hasInsufficientSourcesQuoteIssue) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n const hasEnoughForQuote = hasReadyExactInSwapInput(fromTokens, toToken);\n\n if (!hasEnoughForQuote) {\n clearPendingSwapIntent();\n setSwapQuoteIssue(null);\n setTxError(null);\n return;\n }\n\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n return;\n }\n\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n setQuoteRefreshing(true);\n let quoteStarted = false;\n const quoteDelay = getQuoteRequestDelay();\n const timer = window.setTimeout(() => {\n quoteStarted = true;\n void handleEnterPreview({ background: true });\n }, quoteDelay);\n\n return () => {\n window.clearTimeout(timer);\n if (syncingIntentSourcesRef.current) return;\n if (!quoteStarted && swapStepRef.current === \"idle\") {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n }\n };\n }, [\n activeMode,\n activeQuoteInputKey,\n amount,\n defaultRecipientAddress,\n fromTokensQuoteKey,\n hasCurrentQuoteIntent,\n hasInsufficientSourcesQuoteIssue,\n hasReceiveAmountQuoteIssue,\n getQuoteRequestDelay,\n nexusSDK,\n recipientAddress,\n swapStep,\n toTokenQuoteKey,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\" || swapStep !== \"idle\" || !nexusSDK) return;\n\n if (syncingIntentSourcesRef.current) {\n syncingIntentSourcesRef.current = false;\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n }\n\n if (hasReceiveAmountQuoteIssue) {\n clearPendingSwapIntent(true);\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n if (hasInsufficientSourcesQuoteIssue) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n const parsedAmount = parseFiatNumber(amount);\n const hasEnoughForQuote = Boolean(\n parsedAmount?.gt(0) &&\n toToken &&\n selectedOpportunity &&\n depositTokenAmountForQuote\n );\n\n if (!hasEnoughForQuote) {\n clearPendingSwapIntent();\n clearSelectedSources();\n return;\n }\n\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n return;\n }\n\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n setQuoteRefreshing(true);\n let quoteStarted = false;\n const quoteDelay = getQuoteRequestDelay();\n const timer = window.setTimeout(() => {\n quoteStarted = true;\n void handleEnterPreview({ background: true });\n }, quoteDelay);\n\n return () => {\n window.clearTimeout(timer);\n if (syncingIntentSourcesRef.current) return;\n if (!quoteStarted && swapStepRef.current === \"idle\") {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n }\n };\n }, [\n activeMode,\n amount,\n activeQuoteInputKey,\n depositAmountMode,\n depositQuoteAmountKey,\n hasCurrentQuoteIntent,\n hasInsufficientSourcesQuoteIssue,\n hasReceiveAmountQuoteIssue,\n getQuoteRequestDelay,\n nexusSDK,\n sourceSelectionRevision,\n selectedOpportunityIdentity,\n swapStep,\n toTokenQuoteKey,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"send\" || swapStep !== \"idle\" || !nexusSDK) return;\n\n if (syncingIntentSourcesRef.current) {\n syncingIntentSourcesRef.current = false;\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n }\n\n if (hasReceiveAmountQuoteIssue) {\n clearPendingSwapIntent(true);\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n if (hasInsufficientSourcesQuoteIssue) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n const parsedAmount = parseFiatNumber(amount);\n const hasEnoughForQuote = Boolean(parsedAmount?.gt(0) && toToken);\n\n if (!hasEnoughForQuote) {\n clearPendingSwapIntent();\n clearSelectedSources();\n return;\n }\n\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n return;\n }\n\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n setQuoteRefreshing(true);\n let quoteStarted = false;\n const quoteDelay = getQuoteRequestDelay();\n const timer = window.setTimeout(() => {\n quoteStarted = true;\n void handleEnterPreview({ background: true });\n }, quoteDelay);\n\n return () => {\n window.clearTimeout(timer);\n if (syncingIntentSourcesRef.current) return;\n if (!quoteStarted && swapStepRef.current === \"idle\") {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n }\n };\n }, [\n activeMode,\n amount,\n activeQuoteInputKey,\n hasCurrentQuoteIntent,\n hasInsufficientSourcesQuoteIssue,\n hasReceiveAmountQuoteIssue,\n getQuoteRequestDelay,\n nexusSDK,\n sourceSelectionRevision,\n swapStep,\n toTokenQuoteKey,\n ]);\n\n const refreshActiveSwapIntent = useCallback(async () => {\n if (receiveAmountIssueRef.current) return;\n\n const activeIntent = swapIntentRef.current;\n if (\n !activeIntent ||\n intentLoading ||\n quoteRefreshing ||\n receiveMaxCalculating ||\n previewQuoteRefreshing\n ) {\n return;\n }\n\n const runId = activeIntent.runId;\n const quoteInputKey = activeIntent.quoteInputKey;\n if (!quoteInputKey || activeQuoteInputKeyRef.current !== quoteInputKey) {\n return;\n }\n const isPreviewRefresh = swapStepRef.current === \"preview-intent\";\n if (isPreviewRefresh) {\n setPreviewQuoteRefreshing(true);\n } else {\n setQuoteRefreshing(true);\n }\n try {\n const updatedRaw = await activeIntent.refresh();\n const updatedBridgeProvider = normalizeBridgeProvider(\n (updatedRaw as any)?.bridgeProvider ??\n (updatedRaw as any)?.normalizedIntent?.bridgeProvider ??\n (updatedRaw as any)?.swap?.bridgeProvider ??\n activeIntent.intent?.bridgeProvider\n );\n const updated = normalizeRenderableSwapIntentData(\n updatedRaw,\n updatedBridgeProvider\n );\n if (\n !updated ||\n swapRunIdRef.current !== runId ||\n activeQuoteInputKeyRef.current !== quoteInputKey\n ) {\n return;\n }\n\n if (swapIntentRef.current) {\n swapIntentRef.current.intent = updated;\n }\n applySwapIntent(updated);\n } catch (err) {\n console.error(\"Unable to refresh swap intent\", err);\n } finally {\n if (\n swapRunIdRef.current === runId &&\n activeQuoteInputKeyRef.current === quoteInputKey\n ) {\n if (isPreviewRefresh) {\n setPreviewQuoteRefreshing(false);\n } else {\n setQuoteRefreshing(false);\n }\n }\n }\n }, [\n applySwapIntent,\n intentLoading,\n previewQuoteRefreshing,\n quoteRefreshing,\n receiveMaxCalculating,\n ]);\n\n useEffect(() => {\n const hasRefreshableIntent =\n (activeMode === \"swap\" ||\n activeMode === \"deposit\" ||\n activeMode === \"send\") &&\n Boolean(\n intentData &&\n swapIntentRef.current &&\n swapIntentRef.current.quoteInputKey === activeQuoteInputKey\n ) &&\n (swapStep === \"idle\" || swapStep === \"preview-intent\");\n\n if (!hasRefreshableIntent || receiveAmountIssue) {\n setQuoteRefreshProgress(0);\n setQuoteRefreshSecondsRemaining(0);\n return;\n }\n\n let cancelled = false;\n let timeout: number | undefined;\n\n const scheduleRefresh = () => {\n const quoteAge = Date.now() - lastSwapIntentRefreshAtRef.current;\n const delay = Math.max(0, QUOTE_REFRESH_INTERVAL_MS - quoteAge);\n timeout = window.setTimeout(() => {\n if (receiveAmountIssueRef.current) {\n clearPendingSwapIntent(true);\n setQuoteRefreshProgress(0);\n setQuoteRefreshSecondsRemaining(0);\n return;\n }\n\n if (\n intentLoading ||\n quoteRefreshing ||\n receiveMaxCalculating ||\n previewQuoteRefreshing\n ) {\n if (!cancelled) {\n timeout = window.setTimeout(scheduleRefresh, 1000);\n }\n return;\n }\n\n void refreshActiveSwapIntent().finally(() => {\n if (!cancelled) {\n scheduleRefresh();\n }\n });\n }, delay);\n };\n\n scheduleRefresh();\n\n return () => {\n cancelled = true;\n if (timeout !== undefined) {\n window.clearTimeout(timeout);\n }\n };\n }, [\n activeMode,\n activeQuoteInputKey,\n intentData,\n intentLoading,\n receiveAmountIssue,\n previewQuoteRefreshing,\n quoteRefreshing,\n receiveMaxCalculating,\n refreshActiveSwapIntent,\n swapStep,\n ]);\n\n useEffect(() => {\n const hasRefreshableIntent =\n (activeMode === \"swap\" ||\n activeMode === \"deposit\" ||\n activeMode === \"send\") &&\n Boolean(\n intentData &&\n swapIntentRef.current &&\n swapIntentRef.current.quoteInputKey === activeQuoteInputKey\n ) &&\n (swapStep === \"idle\" || swapStep === \"preview-intent\");\n\n if (!hasRefreshableIntent || receiveAmountIssue) {\n setQuoteRefreshProgress(0);\n setQuoteRefreshSecondsRemaining(0);\n return;\n }\n\n const updateProgress = () => {\n const quoteAge = Date.now() - lastSwapIntentRefreshAtRef.current;\n const remaining = Math.max(0, QUOTE_REFRESH_INTERVAL_MS - quoteAge);\n setQuoteRefreshProgress(remaining / QUOTE_REFRESH_INTERVAL_MS);\n setQuoteRefreshSecondsRemaining(Math.ceil(remaining / 1000));\n };\n\n updateProgress();\n const interval = window.setInterval(updateProgress, 250);\n\n return () => window.clearInterval(interval);\n }, [\n activeMode,\n activeQuoteInputKey,\n intentData,\n receiveAmountIssue,\n swapStep,\n ]);\n\n /** User accepted swap from the preview — call allow() from the intent hook */\n const handleSwapAccept = () => {\n const activeIntent = swapIntentRef.current;\n if (activeIntent) {\n if (\n activeIntent.quoteInputKey &&\n activeQuoteInputKeyRef.current !== activeIntent.quoteInputKey\n ) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n setQuoteRefreshing(true);\n setSwapStep(\"idle\");\n return;\n }\n if (activeMode === \"deposit\") {\n previewConfirmedTsRef.current = Date.now();\n attemptCountRef.current += 1;\n const timeInPreviewMs = previewViewedTsRef.current\n ? previewConfirmedTsRef.current - previewViewedTsRef.current\n : 0;\n trackDeposit(\"deposit_preview_confirmed\", {\n timeInPreviewMs,\n totalFeeUsd: Number(intentFeeUsd) || 0,\n sourceCount: (intentData?.sources ?? []).length,\n });\n }\n onStart?.();\n startSwapHistoryEntry();\n setSwapStep(\"progress\");\n setQuoteRefreshing(false);\n resetProgressEvents();\n if (swapStepsListRef.current.length > 0) {\n seed(swapStepsListRef.current);\n } else {\n resetSteps();\n }\n activeIntent.allow();\n }\n };\n\n // ---------------------------------------------------------------------------\n // Header title\n // ---------------------------------------------------------------------------\n const getTitle = () => {\n const configuredWidgetHeading = normalizeConfiguredString(\n appearanceConfig?.widgetHeading\n );\n if (swapStep === \"history\") return \"Transaction History\";\n // Drawer panels overlay the main page,\n // so the header should still show the main page title.\n\n if (swapStep === \"preview-intent\") {\n return activeMode === \"deposit\"\n ? \"Confirm Deposit\"\n : activeMode === \"send\"\n ? \"Confirm Send\"\n : \"Confirm Swap\";\n }\n\n if (activeMode === \"swap\") {\n if (swapStep === \"progress\") return \"Swapping…\";\n if (swapStep === \"success\") return \"Swap Complete\";\n if (swapStep === \"failed\" && currentSwapEntry?.status === \"timeout\") {\n return TIMEOUT_LABEL;\n }\n if (swapStep === \"failed\") return \"Swap Failed\";\n return configuredWidgetHeading ?? \"Swap and Bridge\";\n }\n if (activeMode === \"deposit\") {\n if (swapStep === \"progress\") return \"Depositing…\";\n if (swapStep === \"success\") return \"Deposit Complete\";\n if (swapStep === \"failed\" && currentSwapEntry?.status === \"timeout\") {\n return TIMEOUT_LABEL;\n }\n if (swapStep === \"failed\") return \"Deposit Failed\";\n return configuredWidgetHeading ?? \"Deposit\";\n }\n if (activeMode === \"send\") {\n if (swapStep === \"progress\") return \"Sending…\";\n if (swapStep === \"success\") return \"Send Complete\";\n if (swapStep === \"failed\" && currentSwapEntry?.status === \"timeout\") {\n return TIMEOUT_LABEL;\n }\n if (swapStep === \"failed\") return \"Send Failed\";\n return configuredWidgetHeading ?? \"Send\";\n }\n return configuredWidgetHeading ?? \"Nexus Widget\";\n };\n\n // Titles that should be center-aligned (main screens / confirm screens)\n // Left-aligned: choose-swap-asset, choose-receive-asset (sub-screens with subtitles)\n const isTitleCentered = () => {\n if (swapStep === \"history\") return false;\n return true; // idle, drawer panels, preview-intent, progress, etc.\n };\n\n const canGoBack = swapStep === \"preview-intent\" || swapStep === \"history\";\n const handleBack = () => {\n if (swapStep === \"history\") {\n setSwapStep(\"idle\");\n return;\n }\n if (swapStep === \"choose-swap-asset\") {\n handleSourcePickerCancel();\n return;\n }\n if (swapStep === \"choose-receive-asset\") {\n closeDrawerToIdle();\n return;\n }\n if (swapStep === \"enter-recipient\") {\n closeDrawerToIdle();\n return;\n }\n if (swapStep === \"preview-intent\") {\n const canRequoteAfterPreviewBack =\n activeMode === \"swap\"\n ? hasReadyExactInSwapInput(fromTokens, toToken)\n : canRefreshExactOutQuote();\n\n if (\n canRequoteAfterPreviewBack &&\n (activeMode === \"deposit\" || activeMode === \"send\")\n ) {\n setExactOutQuoteSourceModeValue(\"all\");\n }\n if (activeMode === \"deposit\" || activeMode === \"send\") {\n invalidateExactOutQuoteForRefresh();\n } else {\n clearPendingSwapIntent(true, {\n keepQuoteRefreshing: canRequoteAfterPreviewBack,\n });\n }\n if (canRequoteAfterPreviewBack && activeMode === \"swap\") {\n setQuoteRefreshing(true);\n setTxError(null);\n setSwapQuoteIssue(null);\n }\n setSwapStep(\"idle\");\n return;\n }\n if (swapStep === \"progress\") {\n return;\n } // can't go back during tx\n setSwapStep(\"idle\");\n };\n\n const handleSwapAmountChange = (val: string, panel: \"send\" | \"receive\") => {\n if (isConfiguredAmountFixed) return;\n syncingIntentSourcesRef.current = false;\n setSwapQuoteIssue(null);\n setTxError(null);\n const nextAmount = parseFiatNumber(val);\n const receiveIssue = buildReceiveAmountIssue({ inputAmount: val });\n applyReceiveAmountIssue(receiveIssue);\n const hasSelectedSourceToken = fromTokens.some(\n (token) => token.chainId && token.contractAddress\n );\n const shouldLoadQuote = Boolean(\n !receiveIssue &&\n nexusSDK &&\n nextAmount?.gt(0) &&\n toToken &&\n hasSelectedSourceToken\n );\n if (!receiveIssue) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: shouldLoadQuote });\n }\n if (shouldLoadQuote) {\n setQuoteRefreshing(true);\n }\n setAmount(val);\n if (panel === \"receive\") {\n setFromTokens((prev) =>\n prev.map((token) => ({ ...token, userAmount: \"\" }))\n );\n }\n // Nexus Widget swaps are exact-in only. Exact-out is reserved for Deposit and Send.\n if (swapType !== \"exactIn\") {\n setSwapType(\"exactIn\");\n }\n };\n\n const handleSwapTokensUpdate = (tokens: SwapTokenOption[]) => {\n setSwapQuoteIssue(null);\n setTxError(null);\n applyReceiveAmountIssue(buildReceiveAmountIssue({ sourceTokens: tokens }));\n setFromTokens(tokens);\n };\n\n const handleDepositAmountChange = (val: string) => {\n if (isConfiguredAmountFixed) return;\n syncingIntentSourcesRef.current = false;\n resetExactOutSourcesToAuto();\n maxPercentRunRef.current += 1;\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setSwapQuoteIssue(null);\n const nextAmount = parseFiatNumber(val);\n const receiveIssue = buildReceiveAmountIssue({ inputAmount: val });\n applyReceiveAmountIssue(receiveIssue);\n const shouldLoadQuote = Boolean(\n !receiveIssue &&\n nexusSDK &&\n nextAmount?.gt(0) &&\n toToken &&\n selectedOpportunity\n );\n if (!receiveIssue) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: shouldLoadQuote });\n }\n if (shouldLoadQuote) {\n setQuoteRefreshing(true);\n } else {\n clearSelectedSources();\n }\n setAmount(val);\n };\n\n const handleSendAmountChange = (val: string) => {\n if (isConfiguredAmountFixed) return;\n syncingIntentSourcesRef.current = false;\n resetExactOutSourcesToAuto();\n maxPercentRunRef.current += 1;\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setSwapQuoteIssue(null);\n setSwapType(\"exactOut\");\n const nextAmount = parseFiatNumber(val);\n const receiveIssue = buildReceiveAmountIssue({\n inputAmount: val,\n type: \"exactOut\",\n });\n applyReceiveAmountIssue(receiveIssue);\n const shouldLoadQuote = Boolean(\n !receiveIssue && nexusSDK && nextAmount?.gt(0) && toToken\n );\n if (!receiveIssue) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: shouldLoadQuote });\n }\n if (shouldLoadQuote) {\n setQuoteRefreshing(true);\n } else {\n clearSelectedSources();\n }\n setAmount(val);\n };\n\n const handleDepositAmountModeToggle = () => {\n if (isConfiguredAmountFixed) return;\n syncingIntentSourcesRef.current = false;\n resetExactOutSourcesToAuto();\n const rate = getDepositTokenUsdRate();\n const parsedAmount = parseFiatNumber(amount) ?? new Decimal(0);\n if (parsedAmount.gt(0) && rate.gt(0)) {\n const converted =\n depositAmountMode === \"token\"\n ? parsedAmount.mul(rate).toDecimalPlaces(2)\n : parsedAmount\n .div(rate)\n .toDecimalPlaces(\n getCappedTokenDisplayDecimals(toToken?.decimals),\n Decimal.ROUND_DOWN\n );\n setAmount(converted.toFixed());\n }\n clearPendingSwapIntent();\n setDepositAmountMode((current) => (current === \"token\" ? \"usd\" : \"token\"));\n };\n\n const handleDepositPercentSelect = async (pct: number) => {\n if (isConfiguredAmountFixed) return;\n if (!toToken) return;\n\n syncingIntentSourcesRef.current = false;\n setTxError(null);\n setSwapQuoteIssue(null);\n const runId = ++maxPercentRunRef.current;\n lastInputMethodRef.current =\n pct === 20\n ? \"percent_20\"\n : pct === 25\n ? \"percent_25\"\n : pct === 50\n ? \"percent_50\"\n : pct === 75\n ? \"percent_75\"\n : \"percent_max\";\n\n if (pct !== 100) {\n const nextAmount = getExactOutPercentAmountFromBalance(\n toToken,\n pct,\n depositAmountMode === \"usd\"\n );\n\n if (nextAmount) {\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setDepositAmountMode(nextAmount.mode);\n handleDepositAmountChange(nextAmount.amount);\n return;\n }\n\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setTxError(\"Unable to calculate this percentage for the deposit asset.\");\n return;\n }\n\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n const maxAmount = getExactOutPercentAmountFromBalance(\n toToken,\n 100,\n depositAmountMode === \"usd\"\n );\n if (runId !== maxPercentRunRef.current) return;\n if (!maxAmount) {\n setTxError(\"No depositable amount is available for this deposit.\");\n return;\n }\n\n setDepositAmountMode(maxAmount.mode);\n handleDepositAmountChange(maxAmount.amount);\n };\n\n const handleSendPercentSelect = async (pct: number) => {\n if (isConfiguredAmountFixed) return;\n if (!toToken) return;\n\n syncingIntentSourcesRef.current = false;\n setTxError(null);\n setSwapQuoteIssue(null);\n const runId = ++maxPercentRunRef.current;\n lastInputMethodRef.current =\n pct === 20\n ? \"percent_20\"\n : pct === 25\n ? \"percent_25\"\n : pct === 50\n ? \"percent_50\"\n : pct === 75\n ? \"percent_75\"\n : \"percent_max\";\n\n if (pct !== 100) {\n const nextAmount = getExactOutPercentAmountFromBalance(\n toToken,\n pct,\n false\n );\n\n if (nextAmount) {\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n handleSendAmountChange(nextAmount.amount);\n return;\n }\n\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setTxError(\"Unable to calculate this percentage for the send asset.\");\n return;\n }\n\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n const maxAmount = getExactOutPercentAmountFromBalance(toToken, 100, false);\n if (runId !== maxPercentRunRef.current) return;\n if (!maxAmount) {\n setTxError(\"No transferable amount is available for this asset.\");\n return;\n }\n\n handleSendAmountChange(maxAmount.amount);\n };\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n const insufficientSourceIssue =\n swapQuoteIssue?.type === \"insufficientSources\" ? swapQuoteIssue : null;\n const configuredAmountIssue = buildConfiguredAmountIssue();\n const blockingQuoteIssue =\n insufficientSourceIssue ?? receiveAmountIssue ?? configuredAmountIssue;\n const isExactOutPaymentFlow =\n activeMode === \"deposit\" || activeMode === \"send\";\n const hasCurrentRunnableIntent = hasCurrentQuoteIntent;\n const hasIntentSources = Boolean((intentData?.sources ?? []).length > 0);\n const hasCurrentExactOutPaymentIntent =\n hasCurrentRunnableIntent &&\n (hasIntentSources ||\n (isExactOutPaymentFlow && Boolean(intentData?.destination)));\n const isExactOutRouteLoading =\n isExactOutPaymentFlow &&\n swapStep === \"idle\" &&\n swapType === \"exactOut\" &&\n Boolean(\n toToken && (receiveMaxCalculating || (amount && Number(amount) > 0))\n ) &&\n !blockingQuoteIssue &&\n !hasCurrentExactOutPaymentIntent &&\n (quoteRefreshing || intentLoading || receiveMaxCalculating);\n const isQuoteUnavailableForAutoSourceFlow =\n isExactOutPaymentFlow &&\n Boolean(hasPositiveDecimalInput(amount) && toToken) &&\n !quoteRefreshing &&\n !receiveMaxCalculating &&\n !intentLoading &&\n !blockingQuoteIssue &&\n !hasCurrentExactOutPaymentIntent;\n const hasPositiveRootAmount = hasPositiveDecimalInput(amount);\n const hasReadySwapQuoteInput = hasReadyExactInSwapInput(fromTokens, toToken);\n const needsWalletConnection = !ownerAddress || !nexusSDK;\n const isExactOutPaymentQuotePending =\n isExactOutPaymentFlow && (quoteRefreshing || intentLoading);\n const walletConnectBusy =\n walletActionPending ||\n nexusLoading ||\n isWalletConnectPending ||\n walletStatus === \"connecting\";\n const hasConnectWalletHandler = Boolean(\n onConnectClick || onConnectWallet || connectors.length > 0\n );\n const walletCtaLabel = hasConnectWalletHandler\n ? walletConnectBusy\n ? \"Connecting...\"\n : \"Connect Wallet\"\n : \"Connect your wallet to proceed\";\n const isSwapCtaDisabled = needsWalletConnection\n ? !hasConnectWalletHandler || walletConnectBusy\n : !hasReadySwapQuoteInput ||\n receiveMaxCalculating ||\n quoteRefreshing ||\n Boolean(blockingQuoteIssue);\n const isDepositCtaDisabled = needsWalletConnection\n ? !hasConnectWalletHandler || walletConnectBusy\n : !hasPositiveRootAmount ||\n !toToken ||\n receiveMaxCalculating ||\n isExactOutPaymentQuotePending ||\n (!hasCurrentExactOutPaymentIntent &&\n isQuoteUnavailableForAutoSourceFlow) ||\n Boolean(blockingQuoteIssue);\n const sendNeedsRecipient = activeMode === \"send\" && !recipientAddress;\n const isSendCtaDisabled = needsWalletConnection\n ? !hasConnectWalletHandler || walletConnectBusy\n : !hasPositiveRootAmount ||\n !toToken ||\n hasSameOwnerSendRecipient ||\n receiveMaxCalculating ||\n (!sendNeedsRecipient &&\n (isExactOutPaymentQuotePending ||\n (!hasCurrentExactOutPaymentIntent &&\n isQuoteUnavailableForAutoSourceFlow))) ||\n Boolean(blockingQuoteIssue);\n const quoteCtaLabel = (fallback: string) => {\n if (needsWalletConnection) return walletCtaLabel;\n if (insufficientSourceIssue) return \"Insufficient balance\";\n if (receiveAmountIssue) return receiveAmountIssue.ctaLabel;\n if (configuredAmountIssue) return configuredAmountIssue.ctaLabel;\n if (receiveMaxCalculating) return \"Calculating...\";\n if (\n isExactOutPaymentQuotePending ||\n (!hasCurrentExactOutPaymentIntent && (quoteRefreshing || intentLoading))\n ) {\n return \"Fetching quotes...\";\n }\n if (isQuoteUnavailableForAutoSourceFlow) return \"Quote unavailable\";\n if (!hasPositiveRootAmount) return \"Enter amount\";\n return fallback;\n };\n const sendCtaLabel = (() => {\n if (needsWalletConnection) return walletCtaLabel;\n if (insufficientSourceIssue) return \"Insufficient balance\";\n if (receiveAmountIssue) return receiveAmountIssue.ctaLabel;\n if (configuredAmountIssue) return configuredAmountIssue.ctaLabel;\n if (!hasPositiveRootAmount) return \"Enter amount\";\n if (!toToken) return \"Select token\";\n if (hasSameOwnerSendRecipient) return \"Change recipient\";\n if (sendNeedsRecipient) return \"Add recipient\";\n return quoteCtaLabel(\"Review send\");\n })();\n const previewIntentSourceUsdNumber = (intentData?.sources ?? []).reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber((source as any).value) ?? new Decimal(0)),\n new Decimal(0)\n );\n const previewSourceUsdNumber = previewIntentSourceUsdNumber.gt(0)\n ? previewIntentSourceUsdNumber\n : fromTokens.length > 0\n ? fromTokens.reduce(\n (sum, token) =>\n sum.plus(\n getTokenUsdValue(\n token,\n swapType === \"exactIn\" && fromTokens.length === 1\n ? amount\n : undefined\n )\n ),\n new Decimal(0)\n )\n : undefined;\n const previewExactOutDestinationAmount =\n activeMode === \"deposit\"\n ? depositTokenAmountForQuote\n : activeMode === \"send\"\n ? parseFiatNumber(amount)\n : undefined;\n const previewExactOutDestinationUsdNumber =\n activeMode === \"deposit\"\n ? depositUsdDecimal\n : activeMode === \"send\" && amount && toToken\n ? getTokenUsdValue(\n {\n ...toToken,\n userAmount: amount,\n userAmountMode: \"token\",\n },\n amount\n )\n : undefined;\n const previewDestinationUsdNumber =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n previewExactOutDestinationUsdNumber?.gt(0)\n ? previewExactOutDestinationUsdNumber\n : parseFiatNumber((intentData?.destination as any)?.value);\n const previewDestinationAmount =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n previewExactOutDestinationAmount?.gt(0)\n ? previewExactOutDestinationAmount\n .toDecimalPlaces(toToken?.decimals ?? 18, Decimal.ROUND_DOWN)\n .toFixed()\n : intentToAmount;\n const previewFromAmountUsd =\n previewSourceUsdNumber && previewSourceUsdNumber.gt(0)\n ? previewSourceUsdNumber.toDecimalPlaces(6).toFixed()\n : undefined;\n const previewToAmountUsd =\n previewDestinationUsdNumber && previewDestinationUsdNumber.gt(0)\n ? previewDestinationUsdNumber.toDecimalPlaces(6).toFixed()\n : undefined;\n const previewDestinationGasFeeUsd = (() => {\n const value = getIntentDestinationGasUsdValue(intentData);\n return value && value.gt(0)\n ? value.toDecimalPlaces(6, Decimal.ROUND_DOWN).toFixed()\n : undefined;\n })();\n const predictiveExactInQuote =\n predictiveQuote?.mode === \"exactIn\" &&\n predictiveQuote.key === getPredictiveQuoteCacheKey(\"swap\", \"exactIn\")\n ? predictiveQuote\n : null;\n const predictiveExactOutQuote =\n predictiveQuote?.mode === \"exactOut\" &&\n predictiveQuote.key === getPredictiveQuoteCacheKey(activeMode, \"exactOut\")\n ? predictiveQuote\n : null;\n const shouldUseCurrentExactOutIntentSources =\n isExactOutPaymentFlow && hasCurrentQuoteIntent && hasIntentSources;\n const currentExactOutIntentSourceTokens =\n shouldUseCurrentExactOutIntentSources\n ? sortSwapTokensByUsdDesc(\n (intentData?.sources ?? [])\n .map(buildIntentSourceToken)\n .filter(hasPositiveSourceSpend)\n )\n : [];\n const resolvedToToken =\n toToken ??\n (activeMode === \"deposit\" && selectedOpportunity\n ? toTokenFromOpportunity(selectedOpportunity)\n : undefined);\n const enrichedResolvedToToken = enrichTokenOptionLogo(resolvedToToken);\n const toTokenWithFetchedBalance =\n enrichedResolvedToToken && destinationBalance\n ? { ...enrichedResolvedToToken, balance: destinationBalance }\n : enrichedResolvedToToken;\n const idleReceiveQuoteAmount =\n activeMode === \"swap\" && swapType === \"exactIn\"\n ? (intentToAmount ?? predictiveExactInQuote?.toAmount)\n : undefined;\n const idleReceiveQuoteUsd =\n activeMode === \"swap\" && swapType === \"exactIn\"\n ? (previewToAmountUsd ?? predictiveExactInQuote?.toUsd)\n : previewToAmountUsd;\n const exactOutDestinationCoverage = getExactOutDestinationBalanceCoverage({\n requestedAmount: previewExactOutDestinationAmount,\n requestedUsd: previewExactOutDestinationUsdNumber,\n producedAmount: hasIntentSources\n ? parseFiatNumber(intentData?.destination?.amount)\n : undefined,\n producedUsd: hasIntentSources\n ? parseFiatNumber(intentData?.destination?.value)\n : undefined,\n token: toTokenWithFetchedBalance,\n });\n const destinationBalanceDisplayToken = buildDestinationBalanceDisplayToken(\n exactOutDestinationCoverage,\n toTokenWithFetchedBalance\n );\n const shouldShowPredictiveExactOutDisplay =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n (quoteRefreshing || intentLoading) &&\n !hasIntentSources &&\n Boolean(\n predictiveExactOutQuote &&\n ((predictiveExactOutQuote.sources?.length ?? 0) > 0 ||\n destinationBalanceDisplayToken)\n );\n const baseDisplayFromTokens = shouldUseCurrentExactOutIntentSources\n ? currentExactOutIntentSourceTokens\n : shouldShowPredictiveExactOutDisplay\n ? (predictiveExactOutQuote?.sources ?? fromTokens)\n : fromTokens;\n const displayFromTokens = (() => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") {\n return baseDisplayFromTokens;\n }\n if (!destinationBalanceDisplayToken) {\n return mergeDisplaySourceTokens(\n sortDisplaySourcesByBalanceUsdDesc(baseDisplayFromTokens)\n );\n }\n\n const destinationKey = getTokenSelectionKey(destinationBalanceDisplayToken);\n let replacedEmptyDestinationToken = false;\n const tokens = baseDisplayFromTokens.map((token) => {\n const isDestinationToken = getTokenSelectionKey(token) === destinationKey;\n if (\n isDestinationToken &&\n !hasPositiveDecimalInput(token.userAmount) &&\n !hasPositiveDecimalInput(token.userAmountUsd)\n ) {\n replacedEmptyDestinationToken = true;\n return destinationBalanceDisplayToken;\n }\n return token;\n });\n\n const displayTokens = replacedEmptyDestinationToken\n ? tokens\n : [...tokens, destinationBalanceDisplayToken];\n return mergeDisplaySourceTokens(\n sortDisplaySourcesByBalanceUsdDesc(displayTokens)\n );\n })();\n const displayExactOutRouteLoading =\n isExactOutRouteLoading && !shouldShowPredictiveExactOutDisplay;\n const isSourcePickerRefreshDisabled =\n quoteRefreshing || intentLoading || previewQuoteRefreshing;\n const isIntentSourceUiActionable =\n activeMode === \"deposit\"\n ? !isDepositCtaDisabled\n : activeMode === \"send\"\n ? !isSendCtaDisabled\n : !isSwapCtaDisabled;\n\n useEffect(() => {\n if (!intentFetchTiming?.endTimeMs) {\n return;\n }\n if (latestIntentFetchRunIdRef.current !== intentFetchTiming.runId) {\n return;\n }\n if (intentUiRenderLoggedRunIdRef.current === intentFetchTiming.runId) {\n return;\n }\n const hasRenderedSources =\n displayFromTokens.length > 0 ||\n hasIntentSources ||\n Boolean(intentData?.destination);\n if (!hasRenderedSources) return;\n if (\n isSwapBalancePending ||\n isSourcePickerRefreshDisabled ||\n quoteRefreshing ||\n intentLoading ||\n previewQuoteRefreshing ||\n receiveMaxCalculating ||\n displayExactOutRouteLoading ||\n !isIntentSourceUiActionable\n ) {\n return;\n }\n\n const renderTimeMs = Date.now();\n const renderDurationMs = renderTimeMs - intentFetchTiming.startTimeMs;\n const fetchDurationMs =\n intentFetchTiming.fetchDurationMs ??\n intentFetchTiming.endTimeMs - intentFetchTiming.startTimeMs;\n const differenceMs = renderDurationMs - fetchDurationMs;\n\n console.log(\"[NexusWidget] intent sources UI render complete\", {\n runId: intentFetchTiming.runId,\n walletAddress: intentFetchTiming.walletAddress,\n operation: intentFetchTiming.operation,\n quoteInputKey: intentFetchTiming.quoteInputKey,\n sourceCount: displayFromTokens.length,\n dateNow: renderTimeMs,\n date: new Date(renderTimeMs),\n totalRenderTimeSeconds: renderDurationMs / 1000,\n elapsedMs: renderDurationMs,\n });\n console.log(\"[NexusWidget] intent render/fetch difference\", {\n runId: intentFetchTiming.runId,\n walletAddress: intentFetchTiming.walletAddress,\n operation: intentFetchTiming.operation,\n quoteInputKey: intentFetchTiming.quoteInputKey,\n differenceMs,\n dateNow: renderTimeMs,\n date: new Date(renderTimeMs),\n });\n intentUiRenderLoggedRunIdRef.current = intentFetchTiming.runId;\n }, [\n displayExactOutRouteLoading,\n displayFromTokens.length,\n hasIntentSources,\n intentLoading,\n intentData?.destination,\n intentFetchTiming,\n isDepositCtaDisabled,\n isIntentSourceUiActionable,\n isSendCtaDisabled,\n isSourcePickerRefreshDisabled,\n isSwapCtaDisabled,\n isSwapBalancePending,\n previewQuoteRefreshing,\n quoteRefreshing,\n receiveMaxCalculating,\n ]);\n\n const totalSwapBalanceUsd = getActiveTotalBalanceUsd()\n .toDecimalPlaces(2)\n .toFixed();\n const requestedOutputUsd =\n amount && toToken\n ? getTokenUsdValue(\n {\n ...toToken,\n userAmount: amount,\n userAmountMode: \"token\",\n },\n amount\n )\n : new Decimal(0);\n const sendAmountUsd = requestedOutputUsd.toNumber();\n const exactOutRequiredUsdAmount = (() => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return undefined;\n\n const issueMissingUsd = parseFiatNumber(insufficientSourceIssue?.missingUsd);\n if (issueMissingUsd && issueMissingUsd.gt(0)) {\n return getExactOutAvailableSourceUsd().plus(issueMissingUsd);\n }\n\n const requiredFundingUsd = getExactOutRequiredFundingUsd();\n if (requiredFundingUsd?.gt(0)) return requiredFundingUsd;\n\n if (requestedOutputUsd.gt(0)) return requestedOutputUsd;\n\n return undefined;\n })();\n const exactOutRequiredUsdDisplay = exactOutRequiredUsdAmount\n ?.toDecimalPlaces(2)\n .toFixed();\n const assetSelectorRequiredUsdDisplay =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n (swapStep === \"choose-swap-asset\" ||\n closingDrawerStep === \"choose-swap-asset\")\n ? (sourceSelectionRequiredUsdDisplay ?? exactOutRequiredUsdDisplay)\n : exactOutRequiredUsdDisplay;\n const captureSourceSelectionRequiredUsd = () => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n setSourceSelectionRequiredUsdDisplay(exactOutRequiredUsdDisplay);\n };\n const isIdleSwapQuoteLoading =\n activeMode === \"swap\" &&\n swapStep === \"idle\" &&\n (quoteRefreshing || intentLoading);\n const isReceiveAmountLoading =\n receiveMaxCalculating ||\n (isIdleSwapQuoteLoading &&\n swapType === \"exactIn\" &&\n !idleReceiveQuoteAmount);\n const isReceiveUsdLoading =\n receiveMaxCalculating ||\n (isIdleSwapQuoteLoading && swapType === \"exactIn\" && !idleReceiveQuoteUsd);\n const hasQuoteRefreshCountdown =\n (activeMode === \"swap\" ||\n activeMode === \"deposit\" ||\n activeMode === \"send\") &&\n hasCurrentQuoteIntent &&\n (swapStep === \"idle\" || swapStep === \"preview-intent\");\n const isRecipientDrawerClosing = closingDrawerStep === \"enter-recipient\";\n const isSwapAssetDrawerClosing = closingDrawerStep === \"choose-swap-asset\";\n const isReceiveAssetDrawerClosing =\n closingDrawerStep === \"choose-receive-asset\";\n const isReceiveAssetPickerLocked =\n activeMode === \"deposit\"\n ? configuredDepositOptions.length <= 1\n : (config.allowedDestinationPairs?.length ?? 0) === 1;\n const hideDestinationTokenDropdownIcon =\n activeMode === \"deposit\"\n ? configuredDepositOptions.length === 1\n : (config.allowedDestinationPairs?.length ?? 0) === 1;\n const isTokenAssetDrawerActive =\n swapStep === \"choose-swap-asset\" ||\n swapStep === \"choose-receive-asset\" ||\n closingDrawerStep === \"choose-swap-asset\" ||\n closingDrawerStep === \"choose-receive-asset\";\n const configuredReceiveTokenCount =\n activeMode === \"deposit\" || activeMode === \"send\"\n ? Math.max(\n configuredDestinationTokenOptions.length,\n config.allowedDestinationPairs?.length ?? 0\n )\n : 0;\n const isConfiguredReceiveAssetDrawerActive =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n (swapStep === \"choose-receive-asset\" ||\n closingDrawerStep === \"choose-receive-asset\") &&\n Boolean(config.allowedDestinationPairs?.length);\n const tokenAssetDrawerMinRootContentHeight =\n isConfiguredReceiveAssetDrawerActive\n ? getConfiguredReceiveSelectorRootHeight(configuredReceiveTokenCount)\n : isTokenAssetDrawerActive\n ? TOKEN_SELECTOR_MIN_ROOT_CONTENT_HEIGHT\n : 0;\n const isDrawerOverlayActive =\n swapStep === \"choose-swap-asset\" ||\n swapStep === \"choose-receive-asset\" ||\n swapStep === \"enter-recipient\" ||\n closingDrawerStep !== null;\n const isPreviewIntentScreen = swapStep === \"preview-intent\";\n const displayedRootContentHeight =\n hasMeasuredRootContent && rootContentHeight\n ? Math.max(\n rootContentHeight,\n tokenAssetDrawerMinRootContentHeight\n )\n : null;\n\n const widgetContent = (\n {\n const transitions = [];\n if (hasMeasuredRootContent && shouldAnimateRootHeight) {\n transitions.push(`height ${ROOT_HEIGHT_TRANSITION_MS}ms ease-out`);\n }\n return transitions.join(\", \");\n })(),\n willChange: \"height\",\n width: \"450px\",\n maxWidth: \"100%\",\n minWidth: \"320px\",\n WebkitFontSmoothing: \"antialiased\",\n MozOsxFontSmoothing: \"grayscale\",\n }}\n >\n \n \n \n
\n {canGoBack && (\n \n \n \n )}\n \n {getTitle()}\n
\n\n {/* Sub-screen asset counts */}\n {!isTitleCentered() &&\n activeMode === \"swap\" &&\n swapStep === \"choose-swap-asset\" &&\n swapType === \"exactIn\" && (\n \n {fromTokens.length} asset(s) selected\n \n )}\n \n\n {/* Right side icons */}\n \n {hasQuoteRefreshCountdown && (\n \n )}\n setSwapStep(\"history\")}\n style={{\n alignItems: \"center\",\n backgroundColor: theme.primitives.iconButton.backgroundColor,\n borderColor: theme.primitives.iconButton.borderColor,\n borderRadius: theme.radius.iconButton,\n borderStyle: \"solid\",\n borderWidth: \"1px\",\n boxShadow: theme.primitives.iconButton.boxShadow,\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n height: \"28px\",\n justifyContent: \"center\",\n width: \"28px\",\n cursor: \"pointer\",\n padding: 0,\n }}\n >\n \n \n \n \n \n \n {showCloseButton && (\n \n \n \n \n \n )}\n \n \n\n {/* ------------------------------------------------------------------ */}\n {/* Main content area */}\n {/* ------------------------------------------------------------------ */}\n \n {/* =============================================================== */}\n {/* SHARED SUB-SCREENS (non-drawer panels) */}\n {/* =============================================================== */}\n {(activeMode === \"swap\" ||\n activeMode === \"send\" ||\n activeMode === \"deposit\") &&\n swapStep !== \"idle\" &&\n swapStep !== \"choose-swap-asset\" &&\n swapStep !== \"choose-receive-asset\" &&\n swapStep !== \"enter-recipient\" && (\n <>\n {/* Panel: preview. */}\n {swapStep === \"preview-intent\" && (\n \n {\n clearPendingSwapIntent();\n setSwapStep(\"idle\");\n }}\n onTransitionChange={setIsPreviewTransitioning}\n opportunity={selectedOpportunity}\n recipientAddress={transferRecipientAddress}\n steps={steps}\n supportedTokenAssets={supportedChainsAndTokens}\n swapBalances={swapBalance}\n swapType={swapType}\n toAmount={previewDestinationAmount}\n toAmountTokens={\n previewDestinationAmount\n ? `${previewDestinationAmount}`\n : undefined\n }\n toAmountUsd={previewToAmountUsd}\n toToken={toTokenWithFetchedBalance}\n totalFeeUsd={intentFeeUsd}\n />\n \n )}\n\n {swapStep === \"progress\" && (\n \n )}\n\n {(swapStep === \"success\" || swapStep === \"failed\") &&\n currentSwapEntry && (\n
\n \n
\n )}\n \n )}\n\n {/* =============================================================== */}\n {/* HISTORY SCREEN */}\n {/* =============================================================== */}\n {swapStep === \"history\" && (\n \n )}\n\n {/* =============================================================== */}\n {/* SWAP IDLE SCREEN */}\n {/* =============================================================== */}\n {activeMode === \"swap\" &&\n [\n \"idle\",\n \"choose-swap-asset\",\n \"choose-receive-asset\",\n \"enter-recipient\",\n ].includes(swapStep) && (\n <>\n {\n handleSwapAmountChange(val, panel);\n }}\n onOpenDestPicker={() =>\n openDrawerStep(\"choose-receive-asset\")\n }\n onOpenRecipientPicker={handleOpenRecipientEditor}\n onOpenSourcePicker={(index) => {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n setEditingAssetIndex(index ?? null);\n beginSourcePickerEdit();\n openDrawerStep(\"choose-swap-asset\");\n }}\n onUpdateTokens={handleSwapTokensUpdate}\n receiveQuoteAmount={\n swapType === \"exactIn\" ? idleReceiveQuoteAmount : undefined\n }\n receiveQuoteUsd={idleReceiveQuoteUsd}\n recipientAddress={effectiveRecipientAddress}\n sourceRouteMessage={insufficientSourceIssue?.message}\n sourceRouteStatus={\n insufficientSourceIssue\n ? \"insufficient\"\n : isExactOutRouteLoading\n ? \"loading\"\n : undefined\n }\n swapType={swapType}\n toToken={toTokenWithFetchedBalance}\n totalBalance={totalSwapBalanceUsd}\n usdValue={amount && usdValue > 0 ? usdValue.toFixed(2) : \"\"}\n />\n\n {receiveAmountIssue && (\n \n )}\n\n {configuredAmountIssue && (\n \n )}\n\n {txError && !blockingQuoteIssue && (\n \n )}\n\n {/* CTA Button */}\n \n {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n void handleEnterPreview();\n }}\n style={{\n alignItems: \"center\",\n backgroundColor: blockingQuoteIssue\n ? \"var(--nexus-widget-error-background, #FCEEED)\"\n : isSwapCtaDisabled\n ? theme.colors.surfaceCool\n : primaryButtonBackground,\n border: blockingQuoteIssue ? \"1px solid var(--nexus-widget-error-border, #F7C4C1)\" : \"none\",\n borderRadius: theme.radius.primaryButton,\n boxShadow:\n blockingQuoteIssue || isSwapCtaDisabled\n ? \"none\"\n : theme.shadows.primaryButton,\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n gap: \"7px\",\n height: \"42px\",\n justifyContent: \"center\",\n marginTop: \"8px\",\n paddingInline: \"16px\",\n cursor: isSwapCtaDisabled ? \"default\" : \"pointer\",\n width: \"100%\",\n }}\n >\n {blockingQuoteIssue ? (\n \n ) : (needsWalletConnection && walletConnectBusy) ||\n quoteRefreshing ||\n receiveMaxCalculating ? (\n \n ) : null}\n \n {needsWalletConnection\n ? walletCtaLabel\n : fromTokens.length === 0\n ? \"Add Assets to Bridge\"\n : quoteCtaLabel(\"Review swap\")}\n \n \n \n \n )}\n\n {/* =============================================================== */}\n {/* DEPOSIT MODE LAYOUT */}\n {/* =============================================================== */}\n {activeMode === \"deposit\" &&\n [\n \"idle\",\n \"choose-swap-asset\",\n \"choose-receive-asset\",\n \"enter-recipient\",\n ].includes(swapStep) && (\n <>\n {selectedOpportunity && (\n <>\n {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n captureSourceSelectionRequiredUsd();\n beginSourcePickerEdit();\n openDrawerStep(\"choose-swap-asset\");\n }}\n onOpenTokenPicker={() =>\n openDrawerStep(\"choose-receive-asset\")\n }\n onSetPercent={handleDepositPercentSelect}\n routeMessage={insufficientSourceIssue?.message}\n routeStatus={\n insufficientSourceIssue\n ? \"insufficient\"\n : displayExactOutRouteLoading\n ? \"loading\"\n : undefined\n }\n showAutoBadge={!sourceSelectionTouched}\n isTokenPickerDisabled={isReceiveAssetPickerLocked}\n hideDestinationTokenDropdownIcon={\n hideDestinationTokenDropdownIcon\n }\n tokenValue={depositTokenDisplay}\n toToken={toTokenWithFetchedBalance}\n totalBalance={totalSwapBalanceUsd}\n usdValue={depositUsdDisplay}\n />\n\n {receiveAmountIssue && (\n \n )}\n\n {configuredAmountIssue && (\n \n )}\n\n {txError && !blockingQuoteIssue && (\n \n )}\n\n \n {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n void handleEnterPreview();\n }}\n style={{\n alignItems: \"center\",\n backgroundColor: blockingQuoteIssue\n ? \"var(--nexus-widget-error-background, #FCEEED)\"\n : isDepositCtaDisabled\n ? theme.colors.surfaceCool\n : primaryButtonBackground,\n border: blockingQuoteIssue\n ? \"1px solid var(--nexus-widget-error-border, #F7C4C1)\"\n : \"none\",\n borderRadius: blockingQuoteIssue\n ? \"4px\"\n : theme.radius.primaryButton,\n boxShadow:\n blockingQuoteIssue || isDepositCtaDisabled\n ? \"none\"\n : theme.shadows.primaryButton,\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n gap: \"7px\",\n height: \"40px\",\n justifyContent: \"center\",\n paddingInline: \"16px\",\n cursor: isDepositCtaDisabled ? \"default\" : \"pointer\",\n width: \"100%\",\n }}\n >\n {blockingQuoteIssue ? (\n \n ) : (needsWalletConnection && walletConnectBusy) ||\n isExactOutPaymentQuotePending ||\n receiveMaxCalculating ? (\n \n ) : null}\n \n {quoteCtaLabel(\"Review deposit\")}\n \n \n \n \n )}\n \n )}\n\n {/* =============================================================== */}\n {/* SEND MODE — recipient first, then amount, then asset */}\n {/* =============================================================== */}\n {activeMode === \"send\" &&\n [\n \"idle\",\n \"choose-swap-asset\",\n \"choose-receive-asset\",\n \"enter-recipient\",\n ].includes(swapStep) && (\n <>\n \n openDrawerStep(\"choose-receive-asset\")\n }\n isRecipientLocked={isConfiguredRecipientLocked}\n onOpenRecipientPicker={\n isConfiguredRecipientLocked\n ? () => undefined\n : handleOpenRecipientEditor\n }\n onOpenSourcePicker={() => {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n setEditingAssetIndex(null);\n captureSourceSelectionRequiredUsd();\n beginSourcePickerEdit();\n openDrawerStep(\"choose-swap-asset\");\n }}\n onSetPercent={handleSendPercentSelect}\n recipientAddress={recipientAddress || \"\"}\n routeMessage={insufficientSourceIssue?.message}\n routeStatus={\n insufficientSourceIssue\n ? \"insufficient\"\n : displayExactOutRouteLoading\n ? \"loading\"\n : undefined\n }\n showAutoBadge={!sourceSelectionTouched}\n toToken={toTokenWithFetchedBalance}\n totalBalance={totalSwapBalanceUsd}\n usdValue={\n amount && sendAmountUsd > 0 ? sendAmountUsd.toFixed(2) : \"\"\n }\n />\n\n {receiveAmountIssue && (\n \n )}\n\n {configuredAmountIssue && (\n \n )}\n\n {txError && !blockingQuoteIssue && (\n \n )}\n\n \n {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n if (sendNeedsRecipient) {\n handleOpenRecipientEditor();\n return;\n }\n void handleEnterPreview();\n }}\n style={{\n alignItems: \"center\",\n backgroundColor: blockingQuoteIssue\n ? \"var(--nexus-widget-error-background, #FCEEED)\"\n : isSendCtaDisabled\n ? theme.colors.surfaceCool\n : primaryButtonBackground,\n border: blockingQuoteIssue ? \"1px solid var(--nexus-widget-error-border, #F7C4C1)\" : \"none\",\n borderRadius: blockingQuoteIssue\n ? \"4px\"\n : theme.radius.primaryButton,\n boxShadow:\n blockingQuoteIssue || isSendCtaDisabled\n ? \"none\"\n : theme.shadows.primaryButton,\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n gap: \"7px\",\n height: \"40px\",\n justifyContent: \"center\",\n paddingInline: \"16px\",\n cursor: isSendCtaDisabled ? \"default\" : \"pointer\",\n width: \"100%\",\n }}\n >\n {blockingQuoteIssue ? (\n \n ) : (needsWalletConnection && walletConnectBusy) ||\n (!sendNeedsRecipient &&\n (isExactOutPaymentQuotePending ||\n receiveMaxCalculating)) ? (\n \n ) : null}\n \n {sendCtaLabel}\n \n \n \n \n )}\n \n \n\n {/* ================================================================== */}\n {/* DRAWER PANELS — rendered as direct children of root widget */}\n {/* so they overlay the main page as bottom drawers */}\n {/* ================================================================== */}\n\n {/* Drawer: enter-recipient */}\n {(activeMode === \"swap\" ||\n activeMode === \"send\" ||\n activeMode === \"deposit\") &&\n swapStep === \"enter-recipient\" && (\n \n {\n setTxError(null);\n closeDrawerToIdle();\n }}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: \"rgba(0,0,0,0.35)\",\n pointerEvents: \"auto\",\n opacity: isRecipientDrawerClosing ? 0 : 1,\n transition: `opacity ${DRAWER_CLOSE_MS}ms ease`,\n }}\n />\n \n \n \n \n \n {\n setTxError(null);\n closeDrawerToIdle();\n }}\n style={{\n alignItems: \"center\",\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${theme.colors.border}`,\n borderRadius: \"8px\",\n cursor: \"pointer\",\n display: \"flex\",\n flexShrink: 0,\n height: \"32px\",\n justifyContent: \"center\",\n padding: 0,\n width: \"32px\",\n }}\n type=\"button\"\n >\n \n \n \n Recipient\n \n \n \n \n \n Wallet Address\n \n {activeMode === \"swap\" && defaultRecipientAddress && (\n \n Reset to default\n \n )}\n \n {\n setRecipientAddress(next);\n if (txError) setTxError(null);\n }}\n onClear={() => setRecipientAddress(\"\")}\n placeholder=\"Wallet address\"\n value={recipientAddress}\n />\n {txError && (\n \n {txError}\n \n )}\n {activeMode === \"send\" && (\n \n Recipient must be different from the connected wallet.\n \n )}\n \n Save\n \n \n \n )}\n\n {/* Drawer: choose-swap-asset */}\n {(activeMode === \"swap\" ||\n activeMode === \"send\" ||\n activeMode === \"deposit\") &&\n swapStep === \"choose-swap-asset\" && (\n \n \n \n {\n if (activeMode === \"swap\") {\n const next = [...fromTokens];\n const targetIndex =\n editingAssetIndex !== null &&\n editingAssetIndex < next.length\n ? editingAssetIndex\n : null;\n const existingToken =\n targetIndex !== null ? next[targetIndex] : undefined;\n const tokenChanged = !isSameTokenSelection(\n existingToken,\n token\n );\n const preservedAmount = tokenChanged\n ? \"\"\n : existingToken?.userAmount ||\n (targetIndex === 0 ? amount : \"\");\n const newToken = {\n ...token,\n userAmount: preservedAmount,\n };\n\n if (targetIndex !== null) {\n next[targetIndex] = newToken;\n } else {\n next.push(newToken);\n }\n\n if (tokenChanged) {\n clearPendingSwapIntent();\n setAmount(getSourceAmountInput(next));\n }\n if (swapType !== \"exactIn\") {\n setSwapType(\"exactIn\");\n }\n setFromTokens(next);\n closeDrawerToIdle();\n } else if (\n activeMode === \"deposit\" ||\n activeMode === \"send\"\n ) {\n handleSourcePickerDraftSelectionChange([\n { ...token, userAmount: \"\" },\n ]);\n }\n }}\n onSelectionChange={\n activeMode === \"deposit\" || activeMode === \"send\"\n ? handleSourcePickerDraftSelectionChange\n : undefined\n }\n onToggle={(token) => {\n const isDepositOrSendSourcePicker =\n activeMode === \"deposit\" || activeMode === \"send\";\n const prevTokens = isDepositOrSendSourcePicker\n ? sourcePickerSelectedTokens\n : fromTokens;\n const isSameSelection = (\n a: SwapTokenOption,\n b: SwapTokenOption\n ) => {\n if (a.isUnified || b.isUnified) {\n return Boolean(\n a.isUnified &&\n b.isUnified &&\n a.unifiedSymbol === b.unifiedSymbol\n );\n }\n return (\n a.contractAddress.toLowerCase() ===\n b.contractAddress.toLowerCase() && a.chainId === b.chainId\n );\n };\n const sourceTokens = token.sourceTokens ?? [];\n const isSameUnifiedGroup = (item: SwapTokenOption) =>\n Boolean(\n item.isUnified &&\n token.isUnified &&\n item.unifiedSymbol === token.unifiedSymbol\n );\n const withDefaultAmount = (item: SwapTokenOption) => ({\n ...item,\n userAmount:\n activeMode === \"swap\" && prevTokens.length === 0\n ? amount\n : \"\",\n });\n const getNextTokens = () => {\n if (\n isDepositOrSendSourcePicker &&\n token.isUnified &&\n sourceTokens.length > 0\n ) {\n const hasUnifiedSelection =\n prevTokens.some(isSameUnifiedGroup);\n const areAllChildrenSelected = sourceTokens.every(\n (source) =>\n prevTokens.some((item) =>\n isSameSelection(item, source)\n )\n );\n const withoutGroup = prevTokens.filter(\n (item) =>\n !isSameUnifiedGroup(item) &&\n !sourceTokens.some((source) =>\n isSameSelection(item, source)\n )\n );\n\n if (hasUnifiedSelection || areAllChildrenSelected) {\n return withoutGroup;\n }\n\n return [\n ...withoutGroup,\n ...sourceTokens.map((source) =>\n withDefaultAmount(source)\n ),\n ];\n }\n\n if (isDepositOrSendSourcePicker && !token.isUnified) {\n const unifiedSelection = prevTokens.find(\n (item) =>\n item.isUnified &&\n item.sourceTokens?.some((source) =>\n isSameSelection(source, token)\n )\n );\n\n if (unifiedSelection?.sourceTokens?.length) {\n const withoutUnified = prevTokens.filter(\n (item) => !isSameSelection(item, unifiedSelection)\n );\n return [\n ...withoutUnified,\n ...unifiedSelection.sourceTokens\n .filter((source) => !isSameSelection(source, token))\n .map((source) => withDefaultAmount(source)),\n ];\n }\n }\n\n const exists = prevTokens.find((item) =>\n isSameSelection(item, token)\n );\n if (exists) {\n return prevTokens.filter(\n (item) => !isSameSelection(item, token)\n );\n }\n const tokenSourceKeys = new Set(\n (token.sourceTokens ?? []).map(\n (source) =>\n `${source.chainId}-${source.contractAddress.toLowerCase()}`\n )\n );\n const next = prevTokens.filter((existing) => {\n if (\n token.isUnified &&\n tokenSourceKeys.has(\n `${existing.chainId}-${existing.contractAddress.toLowerCase()}`\n )\n ) {\n return false;\n }\n if (\n existing.isUnified &&\n existing.sourceTokens?.some(\n (source) =>\n source.chainId === token.chainId &&\n source.contractAddress.toLowerCase() ===\n token.contractAddress.toLowerCase()\n )\n ) {\n return false;\n }\n return true;\n });\n return [...next, withDefaultAmount(token)];\n };\n const nextTokens = getNextTokens();\n\n if (isDepositOrSendSourcePicker) {\n handleSourcePickerDraftSelectionChange(nextTokens);\n } else {\n clearPendingSwapIntent();\n setFromTokens(nextTokens);\n }\n }}\n preserveSelectedBelowMinimum={false}\n requiredUsd={assetSelectorRequiredUsdDisplay}\n selectedTokens={sourcePickerSelectedTokens}\n showBelowMinimumInline={\n activeMode === \"swap\" && swapType === \"exactIn\"\n }\n swapBalance={swapBalance}\n swapSupportedChains={swapSupportedChainsAndTokens}\n title={\n activeMode === \"deposit\" || activeMode === \"send\"\n ? \"Choose Assets to Pay with\"\n : \"Choose assets to send\"\n }\n />\n \n \n )}\n\n {/* Drawer: choose-receive-asset */}\n {(activeMode === \"swap\" ||\n activeMode === \"send\" ||\n activeMode === \"deposit\") &&\n swapStep === \"choose-receive-asset\" && (\n \n \n \n {\n const tokenChanged = !isSameTokenSelection(toToken, token);\n if (tokenChanged) {\n onReceiveAssetChange?.({\n chainId: token.chainId,\n chainName: token.chainName,\n contractAddress: token.contractAddress,\n symbol: token.symbol,\n });\n }\n if (activeMode === \"send\" || activeMode === \"deposit\") {\n setExactOutQuoteSourceModeValue(\"all\");\n if (tokenChanged) {\n clearPendingSwapIntent();\n if (!isConfiguredAmountFixed) {\n setAmount(\"\");\n }\n }\n setSwapType(\"exactOut\");\n if (activeMode === \"deposit\") {\n const nextDeposit = getDepositForTokenSelection(\n configuredDepositOptions,\n token\n );\n if (nextDeposit) {\n setSelectedOpportunity(nextDeposit);\n }\n }\n setToToken(token);\n closeDrawerToIdle();\n return;\n }\n if (tokenChanged) {\n clearPendingSwapIntent();\n }\n if (swapType !== \"exactIn\") {\n setSwapType(\"exactIn\");\n }\n setToToken(token);\n closeDrawerToIdle();\n }}\n />\n \n \n )}\n \n );\n\n if (embed) return widgetContent;\n\n return (\n \n \n \n \n \n {widgetContent}\n \n \n );\n}\n\nexport default NexusWidget;\n", + "content": "// biome-ignore-all lint: NexusWidget registry component from shadcn registry.\n\"use client\";\n\nimport { ERROR_CODES, type EthereumProvider } from \"@avail-project/nexus-core\";\nimport Decimal from \"decimal.js\";\nimport { AlertCircle, ArrowLeft, ChevronDown, Loader2 } from \"lucide-react\";\nimport React, {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport {\n createPublicClient,\n encodeFunctionData,\n erc20Abi,\n http,\n isAddress,\n parseUnits,\n zeroAddress,\n} from \"viem\";\nimport { mainnet } from \"viem/chains\";\nimport { normalize } from \"viem/ens\";\nimport {\n useAccount,\n useConnect,\n useDisconnect,\n useConnectorClient,\n usePublicClient,\n useWalletClient,\n} from \"wagmi\";\nimport { ErrorBoundary } from \"../common/components/ErrorBoundary\";\nimport { useTransactionSteps } from \"../common/tx/useTransactionSteps\";\nimport type {\n BridgeStepType,\n SwapStepType,\n} from \"../common/types/transaction-flow\";\nimport {\n CHAIN_METADATA,\n getShortChainName,\n isSwapSupportedBySdkChainList,\n SUPPORTED_CHAINS,\n TOKEN_CONTRACT_ADDRESSES,\n TOKEN_METADATA,\n} from \"../common/utils/constant\";\nimport { type UserAsset, useNexus } from \"../nexus/NexusProvider\";\nimport { Button } from \"../ui/button\";\nimport { Dialog, DialogContent, DialogTrigger } from \"../ui/dialog\";\nimport { DepositFundingMethod } from \"./components/deposit-funding-method\";\nimport { DepositIdleForm } from \"./components/deposit-idle-form\";\nimport { DepositOnrampFlow } from \"./components/deposit-onramp-flow\";\nimport { OnrampHistoryCard } from \"./components/onramp-history-card\";\nimport { useOnrampHistory } from \"./utils/use-onramp-history\";\nimport type { OnrampHistoryEntry } from \"./utils/onramp-history\";\nimport {\n readOnrampWalletAddress,\n withOnrampWalletTimeout,\n} from \"./utils/use-onramp-wallet\";\nimport {\n type NexusWidgetProgressEvent,\n NexusWidgetProgressScreen,\n} from \"./components/nexus-widget-progress-screen\";\nimport {\n getCachedReceiveTokenMatch,\n preloadReceiveTokens,\n ReceiveAssetSelector,\n} from \"./components/receive-asset-selector\";\nimport { RecipientInput } from \"./components/recipient-input\";\nimport { SendIdleForm } from \"./components/send-idle-form\";\nimport { StatusAlert } from \"./components/status-alerts\";\nimport {\n deriveTokenOptions,\n SwapAssetSelector,\n type SwapTokenOption,\n} from \"./components/swap-asset-selector\";\nimport { SwapIdleForm } from \"./components/swap-idle-form\";\nimport {\n type BridgeProvider,\n type SwapIntentData,\n type SwapIntentDestination,\n type SwapIntentSource,\n SwapIntentPreview,\n} from \"./components/swap-intent-preview\";\nimport {\n NEXUS_WIDGET_DEFAULT_PRIMARY_COLOR,\n NEXUS_WIDGET_FAST_SPINNER_STYLE,\n getNexusWidgetThemeStyle,\n nexusWidgetTheme,\n nexusWidgetInteractionStyles,\n resolveNexusWidgetTheme,\n} from \"./theme\";\nimport {\n NexusWidgetThemeContext,\n useNexusWidgetThemeStyle,\n useResolvedNexusWidgetTheme,\n} from \"./theme-context\";\nimport {\n type NexusWidgetAppearance,\n type NexusWidgetConfig,\n type NexusWidgetDepositConfig,\n type NexusWidgetDestination,\n type NexusWidgetDestinationToken,\n type NexusWidgetDepositOpportunityConfig,\n type NexusWidgetDepositOpportunityMetadata,\n type NexusWidgetMode,\n type NexusWidgetPrefillToken,\n type NexusWidgetProps,\n type NexusWidgetRuntimePrefill,\n type SwapType,\n} from \"./types\";\nimport {\n parseAmount as parseDecimalLoose,\n parseAmount as parseFiatNumber,\n} from \"./utils/amount\";\nimport { findCitreaReceiveToken } from \"./utils/citrea-tokens\";\nimport {\n type DepositSourceFilter,\n getDepositSourceId,\n resolveDepositSourceSelection,\n} from \"./utils/deposit-source-selection\";\n\n// ---------------------------------------------------------------------------\n// Types for swap step machine\n// ---------------------------------------------------------------------------\n\ntype SwapStep =\n | \"idle\" // main screen\n | \"choose-swap-asset\" // pick source token\n | \"choose-receive-asset\" // pick receive token\n | \"enter-recipient\" // pick recipient (send mode)\n | \"preview-intent\" // intent preview card\n | \"progress\" // transaction in flight\n | \"success\" // completed seamlessly\n | \"failed\" // failed swap receipt\n | \"history\"; // transaction history\n\ntype DepositFundingStep = \"method\" | \"wallet\" | \"onramp\";\n\ntype SourceFilterTab = \"all\" | \"native\" | \"stables\" | \"custom\";\n\ntype SwapHistoryStatus =\n | \"pending\"\n | \"fulfilled\"\n | \"failed\"\n | \"timeout\"\n | \"refund-initiated\";\n\ninterface SwapHistoryEntry {\n autoRefundAvailable?: boolean;\n createdAt: number;\n durationSeconds?: number;\n endedAt?: number;\n error?: string;\n failedStepType?: string;\n failureDescription?: string;\n failureMessage?: string;\n feeUsd?: string;\n finalExplorerUrl?: string | null;\n fromTokens: SwapTokenOption[];\n id: string;\n intentData: SwapIntentData | null;\n intentExplorerUrl?: string | null;\n intentId?: number;\n mode: NexusWidgetMode;\n opportunity?: NexusWidgetDepositOpportunityMetadata;\n recipientAddress?: string;\n requestedToAmount?: string;\n requestedToValue?: string;\n sourceExplorerUrl?: string | null;\n startedAt: number;\n status: SwapHistoryStatus;\n toToken?: SwapTokenOption;\n}\n\ntype TransactionHistoryEntry = SwapHistoryEntry | OnrampHistoryEntry;\nconst isOnrampHistoryEntry = (\n entry: TransactionHistoryEntry,\n): entry is OnrampHistoryEntry => \"kind\" in entry && entry.kind === \"onramp\";\n\ntype HistorySourceRow = {\n amount: string;\n chainId?: number;\n chainLogo?: string;\n chainName: string;\n contractAddress?: string;\n key: string;\n symbol: string;\n tokenLogo?: string;\n value?: unknown;\n};\n\ntype SwapQuoteIssue = {\n type: \"insufficientSources\";\n message: string;\n missingUsd?: string;\n};\n\ntype ReceiveAmountIssue = {\n ctaLabel: string;\n message: string;\n type:\n | \"configuredAmountLimit\"\n | \"receiveLimitExceeded\"\n | \"unpricedReceiveToken\";\n};\n\ntype CachedIntentUsdRate = {\n amount: string;\n rate: string;\n updatedAt: number;\n value: string;\n};\n\ntype PredictiveQuote = {\n key: string;\n mode: \"exactIn\" | \"exactOut\";\n sources?: SwapTokenOption[];\n toAmount?: string;\n toUsd?: string;\n};\n\ntype IntentFetchTiming = {\n background: boolean;\n endTimeMs?: number;\n fetchDurationMs?: number;\n operation: string;\n quoteInputKey: string;\n runId: number;\n sourceCount?: number;\n startTimeMs: number;\n walletAddress?: string | null;\n};\n\ntype PredictiveQuoteBaseline = {\n destinationUsdRate: string;\n exactInDestinationAmountPerSourceUsd?: string;\n exactOutSourceUsdPerDestinationUsd?: string;\n updatedAt: number;\n};\n\nconst DESTINATION_RECEIVE_LIMIT_USD_BY_CHAIN_ID: Record = {\n [SUPPORTED_CHAINS.MEGAETH]: 10_000,\n [SUPPORTED_CHAINS.CITREA]: 2000,\n [SUPPORTED_CHAINS.SCROLL]: 500,\n};\n\nconst QUOTE_REFRESH_INTERVAL_MS = 30000;\nconst EXACT_OUT_INPUT_DEBOUNCE_MS = 1300;\nconst DRAWER_CLOSE_MS = 220;\nconst BALANCE_REFRESH_AFTER_TERMINAL_MS = 3000;\nconst MODAL_HEIGHT_TRANSITION_MS = 220;\nconst ROOT_HEIGHT_TRANSITION_MS = 140;\nconst ASSET_SELECTOR_DRAWER_HEIGHT = \"90%\";\nconst TOKEN_SELECTOR_MIN_ROOT_CONTENT_HEIGHT = 620;\nconst CONFIGURED_RECEIVE_SELECTOR_BASE_HEIGHT = 170;\nconst CONFIGURED_RECEIVE_SELECTOR_ROW_HEIGHT = 62;\nconst BASIS_POINTS = 10000;\nconst PREDICTIVE_EXACT_IN_DISCOUNT_BPS = 50;\nconst PREDICTIVE_EXACT_OUT_DESTINATION_BUFFER_PCT = 0.1;\nconst PREDICTIVE_EXACT_OUT_DESTINATION_BUFFER_MAX_USD = 2;\nconst PREDICTIVE_EXACT_OUT_SOURCE_BUFFER_PCT = 0.02;\nconst PREDICTIVE_EXACT_OUT_SOURCE_BUFFER_MAX_USD = 1;\nconst PREDICTIVE_QUOTE_DISPLAY_DECIMALS = 8;\nconst DEPOSIT_TOKEN_DISPLAY_DECIMALS = 8;\nconst ETHEREUM_MAINNET_CHAIN_ID = 1;\nconst SDK_EXACT_OUT_STABLE_SYMBOLS = new Set([\n \"USDC\",\n \"USDT\",\n \"DAI\",\n \"BUSD\",\n \"TUSD\",\n \"FRAX\",\n \"LUSD\",\n \"USDD\",\n \"USDP\",\n \"GUSD\",\n]);\nconst SWAP_HISTORY_STORAGE_KEY_PREFIX = \"nexus-widget-transaction-history-v1\";\nconst TIMEOUT_LABEL = \"Timed Out\";\nconst PROGRESS_EVENT_NAMES = {\n BRIDGE_PLAN_LIST: \"bridge_plan_list\",\n BRIDGE_PLAN_PROGRESS: \"bridge_plan_progress\",\n SWAP_PLAN_LIST: \"swap_plan_list\",\n SWAP_PLAN_PROGRESS: \"swap_plan_progress\",\n} as const;\nconst PLAN_FINAL_STATES = new Set([\"completed\", \"confirmed\", \"submitted\"]);\nconst PLAN_STEP_FUNDS_MAY_HAVE_MOVED_STATES = new Set([\n \"completed\",\n \"confirmed\",\n \"submitted\",\n \"failed\",\n]);\nconst theme = nexusWidgetTheme;\nconst tooltipSurface = \"var(--nexus-widget-surface-raised, #FFFFFE)\";\nconst tooltipText = theme.colors.textStrong;\nconst tooltipBorder = theme.colors.border;\nconst uiFont = theme.fonts.sans;\nconst modalHeightTransitionStyle = {\n interpolateSize: \"allow-keywords\",\n} as React.CSSProperties;\n\nconst getCappedTokenDisplayDecimals = (decimals?: number) => {\n const parsedDecimals = Number(decimals);\n if (!Number.isFinite(parsedDecimals) || parsedDecimals < 0) {\n return DEPOSIT_TOKEN_DISPLAY_DECIMALS;\n }\n return Math.min(Math.floor(parsedDecimals), DEPOSIT_TOKEN_DISPLAY_DECIMALS);\n};\nconst modalHeightTransition = `height ${MODAL_HEIGHT_TRANSITION_MS}ms ease, max-height ${MODAL_HEIGHT_TRANSITION_MS}ms ease`;\n\nconst normalizeSdkExactOutStableSymbol = (symbol?: string) =>\n (symbol ?? \"\")\n .trim()\n .toUpperCase()\n .replaceAll(\"\\u20ae\", \"T\")\n .replaceAll(/[^A-Z0-9]/g, \"\");\n\nconst isSdkExactOutStableSymbol = (symbol?: string) =>\n SDK_EXACT_OUT_STABLE_SYMBOLS.has(normalizeSdkExactOutStableSymbol(symbol));\n\nconst applyPredictiveExactOutBufferUsd = (\n amount: Decimal,\n pct: number,\n maxUsd: number,\n) => Decimal.min(amount.mul(pct), new Decimal(maxUsd));\n\nconst getPredictiveExactOutSourceTargetUsd = (\n destinationUsdNeedingSources: Decimal,\n cachedSourceUsdRatio?: Decimal,\n) => {\n if (destinationUsdNeedingSources.lte(0)) return new Decimal(0);\n if (cachedSourceUsdRatio?.gt(0)) {\n return destinationUsdNeedingSources.mul(cachedSourceUsdRatio);\n }\n\n const destinationBuffer = applyPredictiveExactOutBufferUsd(\n destinationUsdNeedingSources,\n PREDICTIVE_EXACT_OUT_DESTINATION_BUFFER_PCT,\n PREDICTIVE_EXACT_OUT_DESTINATION_BUFFER_MAX_USD,\n );\n const destinationBuffered =\n destinationUsdNeedingSources.plus(destinationBuffer);\n const sourceBuffer = applyPredictiveExactOutBufferUsd(\n destinationBuffered,\n PREDICTIVE_EXACT_OUT_SOURCE_BUFFER_PCT,\n PREDICTIVE_EXACT_OUT_SOURCE_BUFFER_MAX_USD,\n );\n\n return destinationBuffered.plus(sourceBuffer);\n};\n\nconst getSwapHistoryStorageKey = (ownerAddress?: string) =>\n `${SWAP_HISTORY_STORAGE_KEY_PREFIX}:${ownerAddress?.toLowerCase() || \"anonymous\"}`;\n\nconst getTokenSelectionKey = (token?: SwapTokenOption | null) => {\n if (!token) return \"\";\n if (token.isUnified) {\n return `unified:${token.unifiedSymbol ?? token.symbol}`;\n }\n return `${token.chainId ?? \"unknown\"}:${token.contractAddress.toLowerCase()}`;\n};\n\nconst getDisplaySourceTokenKey = (token?: SwapTokenOption | null) => {\n if (!token) return \"\";\n const chainId = token.chainId ?? \"unknown\";\n const address = token.contractAddress?.toLowerCase();\n return address\n ? `${chainId}:${address}`\n : `${chainId}:symbol:${token.symbol.toUpperCase()}`;\n};\n\nconst sumDecimalStrings = (left?: string, right?: string) => {\n const leftAmount = parseDecimalLoose(left) ?? new Decimal(0);\n const rightAmount = parseDecimalLoose(right) ?? new Decimal(0);\n const sum = leftAmount.plus(rightAmount);\n return sum.gt(0) ? sum.toFixed() : undefined;\n};\n\nconst mergeDisplaySourceTokens = (tokens: SwapTokenOption[]) => {\n const merged = new Map();\n\n for (const token of tokens) {\n const key = getDisplaySourceTokenKey(token);\n if (!key) continue;\n const existing = merged.get(key);\n if (!existing) {\n merged.set(key, token);\n continue;\n }\n\n const userAmount = sumDecimalStrings(\n existing.userAmount || existing.balance,\n token.userAmount || token.balance,\n );\n const userAmountUsd = sumDecimalStrings(\n existing.userAmountUsd || existing.balanceInFiat,\n token.userAmountUsd || token.balanceInFiat,\n );\n\n merged.set(key, {\n ...existing,\n balance: userAmount ?? existing.balance,\n balanceInFiat: userAmountUsd ?? existing.balanceInFiat,\n chainLogo: existing.chainLogo || token.chainLogo,\n logo: existing.logo || token.logo,\n userAmount: userAmount ?? existing.userAmount,\n userAmountUsd: userAmountUsd ?? existing.userAmountUsd,\n });\n }\n\n return Array.from(merged.values());\n};\n\nconst getTokenQuoteKey = (token?: SwapTokenOption | null) => {\n if (!token) return \"\";\n return [\n getTokenSelectionKey(token),\n token.symbol ?? \"\",\n token.decimals ?? \"\",\n ].join(\":\");\n};\n\nconst getSourceTokensQuoteKey = (tokens: SwapTokenOption[]) =>\n tokens\n .filter((token) => {\n const amt = token.userAmount ?? \"\";\n const cleaned = amt.replaceAll(/[^0-9.]/g, \"\");\n const num = Number.parseFloat(cleaned);\n return !Number.isNaN(num) && num > 0;\n })\n .map((token) =>\n [\n getTokenSelectionKey(token),\n token.symbol ?? \"\",\n token.decimals ?? \"\",\n token.userAmount ?? \"\",\n token.userAmountUsd ?? \"\",\n token.userAmountMode ?? \"\",\n ].join(\":\"),\n )\n .join(\"|\");\n\nconst getSourceTokenSyncKey = (token: SwapTokenOption) =>\n [\n getTokenSelectionKey(token),\n token.userAmount ?? \"\",\n token.userAmountUsd ?? \"\",\n token.balance ?? \"\",\n token.balanceInFiat ?? \"\",\n ].join(\":\");\n\nconst getSourceTokenListSyncKey = (tokens: SwapTokenOption[]) =>\n tokens.map(getSourceTokenSyncKey).join(\"|\");\n\nconst isSameTokenSelection = (\n a?: SwapTokenOption | null,\n b?: SwapTokenOption | null,\n) => Boolean(a && b && getTokenSelectionKey(a) === getTokenSelectionKey(b));\n\nconst getDepositConfigIdentity = (\n deposit?: NexusWidgetDepositOpportunityMetadata | null,\n) => {\n if (!deposit) return \"\";\n return [\n deposit.chainId,\n deposit.tokenAddress.toLowerCase(),\n deposit.tokenSymbol,\n deposit.tokenDecimals,\n deposit.protocol ?? \"\",\n deposit.title ?? \"\",\n ].join(\":\");\n};\n\nconst isSameDepositConfig = (\n a?: NexusWidgetDepositOpportunityConfig | null,\n b?: NexusWidgetDepositOpportunityConfig | null,\n) => {\n if (!a || !b) return false;\n return getDepositConfigIdentity(a) === getDepositConfigIdentity(b);\n};\n\nconst getConfiguredReceiveSelectorRootHeight = (tokenCount: number) => {\n if (tokenCount <= 0) return TOKEN_SELECTOR_MIN_ROOT_CONTENT_HEIGHT;\n const visibleRows = Math.min(Math.max(tokenCount, 1), 6);\n return Math.min(\n TOKEN_SELECTOR_MIN_ROOT_CONTENT_HEIGHT,\n Math.ceil(\n (CONFIGURED_RECEIVE_SELECTOR_BASE_HEIGHT +\n visibleRows * CONFIGURED_RECEIVE_SELECTOR_ROW_HEIGHT) /\n 0.9,\n ),\n );\n};\n\nconst getConfiguredDeposit = (\n config: RuntimeNexusWidgetConfig,\n): NexusWidgetDepositOpportunityConfig | undefined =>\n config.deposit ?? config.deposits?.[0];\n\ntype RuntimeDestinationPair = {\n chain: number;\n decimals?: number;\n logo?: string;\n symbol?: string;\n token: `0x${string}`;\n};\n\ntype RuntimeNexusWidgetAppearance = NexusWidgetAppearance & {\n logoUrl?: string;\n themeMode?: \"auto\" | \"light\" | \"dark\";\n widgetHeading?: string;\n};\n\ntype RuntimeNexusWidgetConfig = {\n allowedDestinationChains?: number[];\n allowedDestinationPairs?: RuntimeDestinationPair[];\n allowedSourcePairs?: RuntimeDestinationPair[];\n appearance?: RuntimeNexusWidgetAppearance;\n deposit?: NexusWidgetDepositOpportunityConfig;\n deposits?: NexusWidgetDepositOpportunityConfig[];\n mode: NexusWidgetMode;\n prefill?: NexusWidgetRuntimePrefill;\n};\n\ntype RuntimeNexusWidgetAmountInput = {\n max?: string;\n min?: string;\n mode: \"fixed\" | \"user\";\n value?: string;\n};\n\ntype NormalizedNexusWidgetConfig = {\n activeMode: NexusWidgetMode;\n amountInput?: RuntimeNexusWidgetAmountInput;\n appearance?: RuntimeNexusWidgetAppearance;\n config: RuntimeNexusWidgetConfig;\n depositOptions: NexusWidgetDepositOpportunityConfig[];\n enableOnRamp: boolean;\n isAmountFixed: boolean;\n isRecipientLocked: boolean;\n};\n\nconst normalizeConfiguredString = (value: unknown) => {\n if (value === null || value === undefined) return undefined;\n const text = String(value).trim();\n return text || undefined;\n};\n\nconst normalizeConfiguredAddress = (value: unknown) => {\n const text = normalizeConfiguredString(value);\n return text && isAddress(text) ? text : undefined;\n};\n\nconst isPositiveGasLimit = (value: unknown): value is bigint =>\n typeof value === \"bigint\" && value > BigInt(0);\n\nconst normalizePositiveNumericString = (value: unknown) => {\n const text = normalizeConfiguredString(value);\n if (!text) return undefined;\n try {\n const decimal = new Decimal(text);\n return decimal.isFinite() && decimal.gt(0) ? text : undefined;\n } catch {\n return undefined;\n }\n};\n\nconst normalizeNonNegativeNumericString = (value: unknown) => {\n const text = normalizeConfiguredString(value);\n if (!text) return undefined;\n try {\n const decimal = new Decimal(text);\n return decimal.isFinite() && decimal.gte(0) ? text : undefined;\n } catch {\n return undefined;\n }\n};\n\nconst normalizeHttpUrlString = (value: unknown) => {\n const text = normalizeConfiguredString(value);\n if (!text) return undefined;\n return /^https?:\\/\\//i.test(text) ? text : undefined;\n};\n\nconst normalizeNexusWidgetPrimaryColor = (value?: string) => {\n return normalizeConfiguredString(value);\n};\n\nconst expandHexColor = (value: string) => {\n const text = value.trim();\n if (/^#[0-9a-fA-F]{6}$/.test(text)) return text;\n if (/^#[0-9a-fA-F]{3}$/.test(text)) {\n const [r, g, b] = text.slice(1);\n return `#${r}${r}${g}${g}${b}${b}`;\n }\n return undefined;\n};\n\nconst parseNumberComponent = (value: string, max: number) => {\n const text = value.trim();\n if (!text) return undefined;\n if (text.endsWith(\"%\")) {\n const percent = Number.parseFloat(text.slice(0, -1));\n return Number.isFinite(percent)\n ? Math.max(0, Math.min(max, (percent / 100) * max))\n : undefined;\n }\n const parsed = Number.parseFloat(text);\n return Number.isFinite(parsed)\n ? Math.max(0, Math.min(max, parsed))\n : undefined;\n};\n\nconst parseAngleComponent = (value: string) => {\n const parsed = Number.parseFloat(value.trim());\n if (!Number.isFinite(parsed)) return undefined;\n return ((parsed % 360) + 360) % 360;\n};\n\nconst hslToRgb = (\n h: number,\n s: number,\n l: number,\n): [number, number, number] => {\n const saturation = Math.max(0, Math.min(100, s)) / 100;\n const lightness = Math.max(0, Math.min(100, l)) / 100;\n const c = (1 - Math.abs(2 * lightness - 1)) * saturation;\n const hp = h / 60;\n const x = c * (1 - Math.abs((hp % 2) - 1));\n let r1 = 0;\n let g1 = 0;\n let b1 = 0;\n if (hp >= 0 && hp < 1) {\n r1 = c;\n g1 = x;\n } else if (hp >= 1 && hp < 2) {\n r1 = x;\n g1 = c;\n } else if (hp >= 2 && hp < 3) {\n g1 = c;\n b1 = x;\n } else if (hp >= 3 && hp < 4) {\n g1 = x;\n b1 = c;\n } else if (hp >= 4 && hp < 5) {\n r1 = x;\n b1 = c;\n } else {\n r1 = c;\n b1 = x;\n }\n const m = lightness - c / 2;\n return [\n Math.round((r1 + m) * 255),\n Math.round((g1 + m) * 255),\n Math.round((b1 + m) * 255),\n ];\n};\n\nconst parseCssColorToRgb = (\n color: string,\n allowBrowserResolution = true,\n): [number, number, number] | undefined => {\n const text = normalizeConfiguredString(color);\n if (!text) return undefined;\n\n const hex = expandHexColor(text);\n if (hex) {\n return [\n Number.parseInt(hex.slice(1, 3), 16),\n Number.parseInt(hex.slice(3, 5), 16),\n Number.parseInt(hex.slice(5, 7), 16),\n ];\n }\n\n const rgbMatch = text.match(/^rgba?\\((.*)\\)$/i);\n if (rgbMatch) {\n const parts = rgbMatch[1]\n .trim()\n .split(/[\\s,\\/]+/)\n .filter(Boolean);\n if (parts.length >= 3) {\n const r = parseNumberComponent(parts[0], 255);\n const g = parseNumberComponent(parts[1], 255);\n const b = parseNumberComponent(parts[2], 255);\n if (r !== undefined && g !== undefined && b !== undefined) {\n return [Math.round(r), Math.round(g), Math.round(b)];\n }\n }\n }\n\n const hslMatch = text.match(/^hsla?\\((.*)\\)$/i);\n if (hslMatch) {\n const parts = hslMatch[1]\n .trim()\n .split(/[\\s,\\/]+/)\n .filter(Boolean);\n if (parts.length >= 3) {\n const h = parseAngleComponent(parts[0]);\n const s = parseNumberComponent(parts[1], 100);\n const l = parseNumberComponent(parts[2], 100);\n if (h !== undefined && s !== undefined && l !== undefined) {\n return hslToRgb(h, s, l);\n }\n }\n }\n\n if (allowBrowserResolution && typeof document !== \"undefined\") {\n const canvas = document.createElement(\"canvas\");\n const context = canvas.getContext(\"2d\");\n if (context) {\n const baseline = \"#010203\";\n context.fillStyle = baseline;\n context.fillStyle = text;\n const resolved = String(context.fillStyle);\n if (resolved !== baseline || text.toLowerCase() === baseline) {\n return parseCssColorToRgb(resolved, false);\n }\n }\n }\n\n return undefined;\n};\n\nconst getReadableTextColor = (background: string) => {\n const rgb = parseCssColorToRgb(background);\n if (!rgb) return \"#FFFFFE\";\n const [rValue, gValue, bValue] = rgb;\n const r = rValue / 255;\n const g = gValue / 255;\n const b = bValue / 255;\n const linear = [r, g, b].map((channel) =>\n channel <= 0.03928\n ? channel / 12.92\n : Math.pow((channel + 0.055) / 1.055, 2.4),\n );\n const luminance =\n 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];\n return luminance > 0.54 ? \"#161615\" : \"#FFFFFE\";\n};\n\nconst normalizeNexusWidgetAmountInput = (\n config: NexusWidgetConfig,\n): RuntimeNexusWidgetAmountInput | undefined => {\n if (config.mode === \"swap\") return undefined;\n const value = normalizePositiveNumericString(\n \"amount\" in (config.prefill ?? {}) ? config.prefill?.amount : undefined,\n );\n const min = normalizeNonNegativeNumericString(config.validation?.minAmount);\n const max = normalizePositiveNumericString(config.validation?.maxAmount);\n return value || min || max ? { mode: \"user\", value, min, max } : undefined;\n};\n\nconst normalizeNexusWidgetAppearance = (\n appearance?: NexusWidgetAppearance,\n): RuntimeNexusWidgetAppearance | undefined => {\n if (!appearance) return undefined;\n const appName = normalizeConfiguredString(appearance.appName);\n const appLogoURL = normalizeHttpUrlString(appearance.appLogoURL);\n const heading = normalizeConfiguredString(appearance.heading);\n const mode =\n appearance.mode === \"dark\" || appearance.mode === \"light\"\n ? appearance.mode\n : \"system\";\n const primaryColor = normalizeConfiguredString(appearance.primaryColor);\n return {\n ...appearance,\n appLogoURL,\n appName,\n heading,\n logoUrl: appLogoURL,\n mode,\n primaryColor,\n themeMode: mode === \"system\" ? \"auto\" : mode,\n widgetHeading: heading,\n };\n};\n\nconst normalizeConfiguredChainId = (value: unknown) => {\n const chainId = Number(value);\n return Number.isFinite(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nconst getConfiguredDestinationChainId = (\n destination?: NexusWidgetDestination,\n) => normalizeConfiguredChainId(destination?.chain);\n\nconst getConfiguredDestinationTokenSymbol = (\n token: NexusWidgetDestinationToken,\n) => normalizeConfiguredString(token.symbol);\n\nconst getConfiguredDestinationTokenAddress = (\n token: NexusWidgetDestinationToken,\n) => normalizeConfiguredAddress(token.address);\n\nconst toSwapTokenOptionFromConfiguredDestinationToken = (\n token: NexusWidgetDestinationToken,\n chainId: number,\n): SwapTokenOption | undefined => {\n const contractAddress = getConfiguredDestinationTokenAddress(token);\n const symbol = getConfiguredDestinationTokenSymbol(token);\n if (!contractAddress || !symbol) return undefined;\n const chainMeta = CHAIN_METADATA[chainId];\n return {\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n chainId,\n chainLogo: chainMeta?.logo,\n chainName: getShortChainName(\n chainId,\n chainMeta?.name ?? `Chain ${chainId}`,\n ),\n contractAddress,\n decimals: token.decimals ?? 18,\n logo: token.logo ?? \"\",\n name: symbol,\n symbol,\n };\n};\n\nconst toSwapTokenOptionFromDepositConfig = (\n deposit: NexusWidgetDepositOpportunityConfig,\n): SwapTokenOption => {\n const chainMeta = CHAIN_METADATA[deposit.chainId];\n return {\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n chainId: deposit.chainId,\n chainLogo: chainMeta?.logo,\n chainName: getShortChainName(\n deposit.chainId,\n chainMeta?.name ?? `Chain ${deposit.chainId}`,\n ),\n contractAddress: deposit.tokenAddress,\n decimals: deposit.tokenDecimals,\n logo: deposit.tokenLogo || deposit.logo || \"\",\n name: deposit.tokenSymbol,\n symbol: deposit.tokenSymbol,\n };\n};\n\nconst applyNexusWidgetAppearanceToDeposit = (\n deposit: NexusWidgetDepositOpportunityConfig,\n appearance?: RuntimeNexusWidgetAppearance,\n): NexusWidgetDepositOpportunityConfig => {\n const appName = normalizeConfiguredString(appearance?.appName);\n const logoUrl = normalizeConfiguredString(appearance?.logoUrl);\n if (!appName && !logoUrl) return deposit;\n return {\n ...deposit,\n depositTargetLogo: logoUrl ?? deposit.depositTargetLogo,\n logo: logoUrl ?? deposit.logo,\n protocol: appName ?? deposit.protocol,\n title: appName ?? deposit.title,\n };\n};\n\nconst getConfiguredDestinationPairs = (\n destination?: NexusWidgetDestination,\n) => {\n const pairs: RuntimeNexusWidgetConfig[\"allowedDestinationPairs\"] = [];\n const chain = getConfiguredDestinationChainId(destination);\n if (!chain) return pairs;\n for (const token of destination?.tokens ?? []) {\n const address = getConfiguredDestinationTokenAddress(token);\n if (!address) continue;\n pairs.push({ chain, token: address });\n }\n return pairs;\n};\n\nconst hasConfiguredDestinationTokenList = (\n destination?: NexusWidgetDestination,\n) => Boolean(destination?.tokens?.length);\n\nconst getConfiguredPrefillTokenPair = (prefill?: {\n token?: NexusWidgetPrefillToken;\n}): RuntimeDestinationPair | undefined => {\n const token = prefill?.token;\n if (!token) return undefined;\n const chain = normalizeConfiguredChainId(token.chain);\n const address = getConfiguredDestinationTokenAddress(token);\n const symbol = getConfiguredDestinationTokenSymbol(token);\n if (!chain || !address || !symbol) return undefined;\n return {\n chain,\n decimals: token.decimals,\n logo: normalizeConfiguredString(token.logo),\n symbol,\n token: address,\n };\n};\n\nconst getConfiguredDestinationChainIds = (\n destination?: NexusWidgetDestination,\n) => {\n const chain = getConfiguredDestinationChainId(destination);\n return chain ? [chain] : [];\n};\n\nconst toDepositConfigFromDestination = (\n config: NexusWidgetDepositConfig,\n token: NexusWidgetDestinationToken,\n appearance?: RuntimeNexusWidgetAppearance,\n): NexusWidgetDepositOpportunityConfig | undefined => {\n const chainId = getConfiguredDestinationChainId(config.destination);\n const depositAddress = normalizeConfiguredAddress(config.depositAddress);\n const tokenAddress = getConfiguredDestinationTokenAddress(token);\n const tokenSymbol = getConfiguredDestinationTokenSymbol(token);\n if (\n !chainId ||\n !depositAddress ||\n !tokenAddress ||\n !tokenSymbol ||\n typeof config.executeDeposit !== \"function\"\n ) {\n return undefined;\n }\n\n const chainMeta = CHAIN_METADATA[chainId];\n return {\n chainId,\n depositTargetLogo: appearance?.logoUrl,\n executeDeposit: config.executeDeposit,\n logo: appearance?.logoUrl ?? token.logo ?? undefined,\n protocol: appearance?.appName ?? appearance?.widgetHeading ?? \"Deposit\",\n subtitle: chainMeta?.name\n ? `on ${getShortChainName(chainId, chainMeta.name)}`\n : undefined,\n title: appearance?.appName ?? appearance?.widgetHeading ?? \"Deposit\",\n tokenAddress,\n tokenDecimals: token.decimals ?? 18,\n tokenLogo: token.logo,\n tokenSymbol,\n };\n};\n\nconst getNexusWidgetDepositOptions = (\n config: NexusWidgetConfig,\n appearance?: RuntimeNexusWidgetAppearance,\n) => {\n if (config.mode !== \"deposit\") return [];\n return (config.destination.tokens ?? [])\n .map((token) => toDepositConfigFromDestination(config, token, appearance))\n .filter((deposit): deposit is NexusWidgetDepositOpportunityConfig =>\n Boolean(deposit),\n );\n};\n\nconst normalizeNexusWidgetConfig = (\n rawConfig: NexusWidgetConfig,\n): NormalizedNexusWidgetConfig => {\n const appearance = normalizeNexusWidgetAppearance(rawConfig.appearance);\n const amountInput = normalizeNexusWidgetAmountInput(rawConfig);\n const prefill: NexusWidgetRuntimePrefill = {};\n let activeMode: NexusWidgetMode =\n rawConfig.mode === \"deposit\" ||\n rawConfig.mode === \"send\" ||\n rawConfig.mode === \"swap\"\n ? rawConfig.mode\n : \"swap\";\n let isRecipientLocked = false;\n const depositOptions = getNexusWidgetDepositOptions(\n rawConfig,\n appearance,\n ).map((deposit) => applyNexusWidgetAppearanceToDeposit(deposit, appearance));\n let allowedDestinationPairs:\n | RuntimeNexusWidgetConfig[\"allowedDestinationPairs\"]\n | undefined;\n let allowedDestinationChains:\n | RuntimeNexusWidgetConfig[\"allowedDestinationChains\"]\n | undefined;\n\n if (amountInput?.value) {\n prefill.amount = amountInput.value;\n }\n\n if (rawConfig.mode === \"deposit\") {\n activeMode = \"deposit\";\n const pairs = getConfiguredDestinationPairs(rawConfig.destination);\n if (pairs.length > 0) {\n allowedDestinationPairs = pairs;\n prefill.destination = pairs[0];\n }\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (chainIds.length > 0) {\n allowedDestinationChains = chainIds;\n }\n } else if (rawConfig.mode === \"send\") {\n const recipient = normalizeConfiguredAddress(rawConfig.recipientAddress);\n if (recipient) {\n prefill.recipient = recipient;\n isRecipientLocked = true;\n }\n\n const hasDestinationTokens = hasConfiguredDestinationTokenList(\n rawConfig.destination,\n );\n const pairs = getConfiguredDestinationPairs(rawConfig.destination);\n if (pairs.length > 0) {\n allowedDestinationPairs = pairs;\n prefill.destination ??= pairs[0];\n } else if (!hasDestinationTokens) {\n const prefillToken = getConfiguredPrefillTokenPair(rawConfig.prefill);\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (\n prefillToken &&\n (!chainIds.length || chainIds.includes(prefillToken.chain))\n ) {\n prefill.destination = prefillToken;\n }\n }\n\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (chainIds.length > 0) {\n allowedDestinationChains = chainIds;\n }\n } else if (rawConfig.mode === \"swap\") {\n const recipient = normalizeConfiguredAddress(rawConfig.recipientAddress);\n if (recipient) {\n prefill.recipient = recipient;\n }\n\n const hasDestinationTokens = hasConfiguredDestinationTokenList(\n rawConfig.destination,\n );\n const pairs = getConfiguredDestinationPairs(rawConfig.destination);\n if (pairs.length > 0) {\n allowedDestinationPairs = pairs;\n prefill.destination ??= pairs[0];\n } else if (!hasDestinationTokens) {\n const prefillToken = getConfiguredPrefillTokenPair(rawConfig.prefill);\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (\n prefillToken &&\n (!chainIds.length || chainIds.includes(prefillToken.chain))\n ) {\n prefill.destination = prefillToken;\n }\n }\n\n const chainIds = getConfiguredDestinationChainIds(rawConfig.destination);\n if (chainIds.length > 0) {\n allowedDestinationChains = chainIds;\n }\n }\n\n const runtimeConfig: RuntimeNexusWidgetConfig = {\n allowedDestinationChains,\n allowedDestinationPairs,\n deposit: activeMode === \"deposit\" ? depositOptions[0] : undefined,\n deposits: activeMode === \"deposit\" ? depositOptions : [],\n appearance,\n mode: activeMode,\n prefill,\n };\n\n return {\n activeMode,\n amountInput,\n appearance,\n config: runtimeConfig,\n depositOptions,\n enableOnRamp:\n rawConfig.mode === \"deposit\" && rawConfig.enableOnRamp === true,\n isAmountFixed: false,\n isRecipientLocked,\n };\n};\n\nconst getDepositForTokenSelection = (\n deposits: NexusWidgetDepositOpportunityConfig[],\n token?: SwapTokenOption | null,\n) => {\n if (!token) return undefined;\n return deposits.find(\n (deposit) =>\n deposit.chainId === token.chainId &&\n deposit.tokenAddress.toLowerCase() ===\n token.contractAddress.toLowerCase(),\n );\n};\n\nconst sanitizeOpportunityForHistory = (\n opportunity?: NexusWidgetDepositOpportunityMetadata,\n): NexusWidgetDepositOpportunityMetadata | undefined => {\n if (!opportunity) return undefined;\n return {\n label: opportunity.label,\n protocol: opportunity.protocol,\n logo: opportunity.logo,\n title: opportunity.title,\n subtitle: opportunity.subtitle,\n chainId: opportunity.chainId,\n tokenSymbol: opportunity.tokenSymbol,\n tokenDecimals: opportunity.tokenDecimals,\n tokenLogo: opportunity.tokenLogo,\n tokenAddress: opportunity.tokenAddress,\n apy: opportunity.apy,\n description: opportunity.description,\n };\n};\n\nconst sanitizeHistoryEntry = (entry: SwapHistoryEntry): SwapHistoryEntry => ({\n ...entry,\n createdAt: entry.createdAt ?? entry.startedAt ?? Date.now(),\n failureMessage:\n entry.status === \"timeout\" ? TIMEOUT_LABEL : entry.failureMessage,\n opportunity: sanitizeOpportunityForHistory(entry.opportunity),\n});\n\nconst sortSwapHistoryEntries = <\n T extends { createdAt: number; startedAt: number },\n>(\n entries: T[],\n) =>\n [...entries].sort(\n (a, b) =>\n (b.createdAt ?? b.startedAt ?? 0) - (a.createdAt ?? a.startedAt ?? 0),\n );\n\nconst isStoredHistoryStatus = (value: unknown): value is SwapHistoryStatus =>\n value === \"pending\" ||\n value === \"fulfilled\" ||\n value === \"failed\" ||\n value === \"timeout\" ||\n value === \"refund-initiated\";\n\nconst isStoredMode = (value: unknown): value is NexusWidgetMode =>\n value === \"swap\" || value === \"deposit\" || value === \"send\";\n\nconst normalizeStoredHistoryEntry = (\n value: unknown,\n): SwapHistoryEntry | null => {\n if (!value || typeof value !== \"object\") return null;\n const entry = value as Partial;\n const startedAt =\n typeof entry.startedAt === \"number\" && Number.isFinite(entry.startedAt)\n ? entry.startedAt\n : undefined;\n const createdAt =\n typeof entry.createdAt === \"number\" && Number.isFinite(entry.createdAt)\n ? entry.createdAt\n : startedAt;\n\n if (\n !entry.id ||\n typeof entry.id !== \"string\" ||\n !isStoredMode(entry.mode) ||\n !isStoredHistoryStatus(entry.status) ||\n !createdAt ||\n !startedAt\n ) {\n return null;\n }\n\n return {\n ...entry,\n id: entry.id,\n mode: entry.mode,\n status: entry.status,\n createdAt,\n startedAt,\n failureMessage:\n entry.status === \"timeout\" ? TIMEOUT_LABEL : entry.failureMessage,\n intentData: entry.intentData ?? null,\n fromTokens: Array.isArray(entry.fromTokens) ? entry.fromTokens : [],\n opportunity: sanitizeOpportunityForHistory(entry.opportunity),\n } as SwapHistoryEntry;\n};\n\nconst readSwapHistoryFromStorage = (storageKey: string): SwapHistoryEntry[] => {\n if (typeof window === \"undefined\") return [];\n\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (!raw) return [];\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n return sortSwapHistoryEntries(\n parsed\n .map(normalizeStoredHistoryEntry)\n .filter((entry): entry is SwapHistoryEntry => Boolean(entry)),\n );\n } catch {\n return [];\n }\n};\n\nconst writeSwapHistoryToStorage = (\n storageKey: string,\n entries: SwapHistoryEntry[],\n) => {\n if (typeof window === \"undefined\") return;\n\n try {\n const persistableEntries =\n sortSwapHistoryEntries(entries).map(sanitizeHistoryEntry);\n window.localStorage.setItem(\n storageKey,\n JSON.stringify(persistableEntries, (_key, value) =>\n typeof value === \"bigint\" ? value.toString() : value,\n ),\n );\n } catch {\n // localStorage can be unavailable or full; in-memory history still works.\n }\n};\n\nfunction QuoteRefreshCountdown({\n progress,\n isRefreshing,\n secondsRemaining,\n}: {\n progress: number;\n isRefreshing: boolean;\n secondsRemaining: number;\n}) {\n const [showTooltip, setShowTooltip] = useState(false);\n const radius = 7;\n const circumference = 2 * Math.PI * radius;\n const clampedProgress = Math.max(0, Math.min(1, progress));\n const tooltipLabel = isRefreshing\n ? \"Refreshing quotes...\"\n : `Refreshing quotes in ${Math.max(0, secondsRemaining)} second${\n secondsRemaining === 1 ? \"\" : \"s\"\n }`;\n\n return (\n setShowTooltip(false)}\n onFocus={() => setShowTooltip(true)}\n onMouseEnter={() => setShowTooltip(true)}\n onMouseLeave={() => setShowTooltip(false)}\n style={{\n alignItems: \"center\",\n backgroundColor: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n height: \"22px\",\n justifyContent: \"center\",\n outline: \"1px solid var(--nexus-widget-border, #E8E8E7)\",\n position: \"relative\",\n width: \"22px\",\n }}\n tabIndex={0}\n >\n {showTooltip && (\n \n {tooltipLabel}\n \n )}\n \n \n \n \n \n );\n}\n\nconst toViemDecimalString = (value: unknown, decimals: number) => {\n const parsed = parseDecimalLoose(value);\n if (!parsed || parsed.lte(0)) return \"0\";\n return parsed\n .toDecimalPlaces(Math.max(0, decimals), Decimal.ROUND_DOWN)\n .toFixed();\n};\n\nconst formatDecimalDisplay = (\n value: unknown,\n options: { min?: number; max?: number } = {},\n) => {\n const amount = parseDecimalLoose(value) ?? new Decimal(0);\n const max = options.max ?? 2;\n return amount.toDecimalPlaces(max).toFixed();\n};\n\nconst formatUsdDisplay = (value: unknown) => {\n const amount = parseDecimalLoose(value) ?? new Decimal(0);\n if (amount.gt(0) && amount.lt(0.01)) return \"<$0.01\";\n return `$${formatDecimalDisplay(amount, { min: 2, max: 2 })}`;\n};\n\nconst formatTokenDisplay = (value: unknown) => {\n const amount = parseDecimalLoose(value) ?? new Decimal(0);\n return formatDecimalDisplay(amount, { max: 8 });\n};\n\nconst getSwapTokenUsdValue = (token: SwapTokenOption) =>\n parseDecimalLoose(token.userAmountUsd) ??\n parseDecimalLoose(token.balanceInFiat) ??\n new Decimal(0);\n\nconst getSwapTokenBalanceUsdValue = (token: SwapTokenOption) =>\n parseDecimalLoose(token.balanceInFiat) ?? new Decimal(0);\n\nconst sortSwapTokensByUsdDesc = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const usdDelta = getSwapTokenUsdValue(b).cmp(getSwapTokenUsdValue(a));\n if (usdDelta !== 0) return usdDelta;\n return (a.symbol ?? \"\").localeCompare(b.symbol ?? \"\");\n });\n\nconst sortDisplaySourcesByBalanceUsdDesc = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const balanceUsdDelta = getSwapTokenBalanceUsdValue(b).cmp(\n getSwapTokenBalanceUsdValue(a),\n );\n if (balanceUsdDelta !== 0) return balanceUsdDelta;\n\n const spendUsdDelta = getSwapTokenUsdValue(b).cmp(getSwapTokenUsdValue(a));\n if (spendUsdDelta !== 0) return spendUsdDelta;\n\n return `${a.symbol ?? \"\"} ${a.chainName ?? \"\"}`.localeCompare(\n `${b.symbol ?? \"\"} ${b.chainName ?? \"\"}`,\n );\n });\n\nconst getIntentSourceUsdValue = (source: SwapIntentData[\"sources\"][number]) =>\n parseDecimalLoose(source.value) ?? new Decimal(0);\n\nconst sortIntentSourcesByUsdDesc = (sources: SwapIntentData[\"sources\"]) =>\n [...sources].sort((a, b) => {\n const usdDelta = getIntentSourceUsdValue(b).cmp(getIntentSourceUsdValue(a));\n if (usdDelta !== 0) return usdDelta;\n return (a.token?.symbol ?? \"\").localeCompare(b.token?.symbol ?? \"\");\n });\n\nconst extractIntentIdFromUrl = (url?: string | null) => {\n if (!url) return undefined;\n const match = url.match(/(\\d+)(?:\\/)?$/);\n if (!match) return undefined;\n const parsed = Number(match[1]);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n};\n\nconst getNonEmptyString = (...values: unknown[]) => {\n for (const value of values) {\n if (typeof value !== \"string\") continue;\n const trimmed = value.trim();\n if (trimmed.length > 0) return trimmed;\n }\n return null;\n};\n\nconst isHttpUrl = (value?: string | null): value is string =>\n Boolean(value && /^https?:\\/\\//i.test(value));\n\nconst hasValidIntentExplorer = (\n entry: Pick,\n) => isHttpUrl(entry.intentExplorerUrl);\n\nconst getHistoryExplorerUrl = (\n entry: Pick<\n SwapHistoryEntry,\n \"finalExplorerUrl\" | \"intentExplorerUrl\" | \"sourceExplorerUrl\"\n >,\n) =>\n [\n entry.intentExplorerUrl,\n entry.finalExplorerUrl,\n entry.sourceExplorerUrl,\n ].find(isHttpUrl) ?? null;\n\nconst getFiniteNumber = (...values: unknown[]) => {\n for (const value of values) {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"string\") continue;\n const parsed = Number(value);\n if (Number.isFinite(parsed)) return parsed;\n }\n return undefined;\n};\n\nconst getObjectChainId = (value: any) =>\n getFiniteNumber(\n value?.chainId,\n value?.chain?.id,\n value?.chain?.chainId,\n value?.toChainId,\n value?.destinationChainId,\n value?.data?.chainId,\n value?.data?.chain?.id,\n value?.data?.chain?.chainId,\n value?.data?.toChainId,\n value?.data?.destinationChainId,\n value?.result?.chainId,\n value?.result?.chain?.id,\n );\n\nconst getExplorerBaseUrl = (chainId?: number, ...candidates: unknown[]) => {\n const directCandidates = candidates.flatMap((candidate: any) => [\n candidate?.blockExplorerUrl,\n candidate?.blockExplorerURL,\n candidate?.chainBlockExplorerUrl,\n candidate?.explorerBaseUrl,\n candidate?.explorerUrlBase,\n candidate?.blockExplorerUrls?.[0],\n candidate?.blockExplorers?.default?.url,\n candidate?.chain?.blockExplorerUrl,\n candidate?.chain?.blockExplorerURL,\n candidate?.chain?.chainBlockExplorerUrl,\n candidate?.chain?.explorerBaseUrl,\n candidate?.chain?.explorerUrlBase,\n candidate?.chain?.blockExplorerUrls?.[0],\n candidate?.chain?.blockExplorers?.default?.url,\n candidate?.data?.blockExplorerUrl,\n candidate?.data?.blockExplorerURL,\n candidate?.data?.chainBlockExplorerUrl,\n candidate?.data?.blockExplorerUrls?.[0],\n candidate?.data?.blockExplorers?.default?.url,\n candidate?.data?.chain?.blockExplorerUrl,\n candidate?.data?.chain?.blockExplorerURL,\n candidate?.data?.chain?.chainBlockExplorerUrl,\n candidate?.data?.chain?.blockExplorerUrls?.[0],\n candidate?.data?.chain?.blockExplorers?.default?.url,\n ]);\n return getNonEmptyString(\n ...directCandidates,\n chainId ? CHAIN_METADATA[chainId]?.blockExplorerUrls?.[0] : undefined,\n chainId\n ? (CHAIN_METADATA[chainId] as any)?.blockExplorers?.default?.url\n : undefined,\n );\n};\n\nconst getTransactionHash = (...values: unknown[]) => {\n for (const value of values) {\n if (typeof value !== \"string\") continue;\n const trimmed = value.trim();\n if (/^0x[a-fA-F0-9]{64}$/.test(trimmed)) return trimmed;\n }\n return null;\n};\n\nconst getIntentHash = (...values: unknown[]) => getTransactionHash(...values);\n\nconst getObjectIntentHash = (value: any) =>\n getIntentHash(\n value?.intentHash,\n value?.intent_hash,\n value?.intent?.hash,\n value?.intent?.intentHash,\n value?.intent?.intent_hash,\n value?.requestHash,\n value?.request_hash,\n value?.request?.hash,\n value?.request?.requestHash,\n value?.rffHash,\n value?.rff_hash,\n value?.rff?.hash,\n value?.data?.intentHash,\n value?.data?.intent_hash,\n value?.data?.intent?.hash,\n value?.data?.intent?.intentHash,\n value?.data?.intent?.intent_hash,\n value?.data?.requestHash,\n value?.data?.request_hash,\n value?.data?.request?.hash,\n value?.data?.request?.requestHash,\n value?.data?.rffHash,\n value?.data?.rff_hash,\n value?.data?.rff?.hash,\n value?.result?.intentHash,\n value?.result?.intent_hash,\n value?.result?.intent?.hash,\n value?.result?.requestHash,\n value?.result?.request_hash,\n value?.result?.rffHash,\n value?.result?.rff_hash,\n );\n\nconst getNexusExplorerNetwork = (network?: unknown) => {\n const normalized =\n typeof network === \"string\" ? network.trim().toLowerCase() : \"\";\n if (normalized === \"canary\" || normalized === \"testnet\") return normalized;\n return \"mainnet\";\n};\n\nconst getRffExplorerUrl = (network: unknown, intentHash?: string | null) =>\n intentHash\n ? `https://nexus-v2.${getNexusExplorerNetwork(network)}.avail.so/rff/${intentHash}`\n : null;\n\nconst getObjectTransactionHash = (value: any) =>\n getTransactionHash(\n value?.txHash,\n value?.transactionHash,\n value?.executeTxHash,\n value?.executeTransactionHash,\n value?.transferTransactionHash,\n value?.receipt?.transactionHash,\n value?.tx?.hash,\n value?.transaction?.hash,\n value?.data?.txHash,\n value?.data?.transactionHash,\n value?.data?.executeTxHash,\n value?.data?.executeTransactionHash,\n value?.data?.transferTransactionHash,\n value?.data?.receipt?.transactionHash,\n value?.data?.tx?.hash,\n value?.data?.transaction?.hash,\n value?.result?.txHash,\n value?.result?.transactionHash,\n value?.result?.receipt?.transactionHash,\n );\n\nconst getExplorerTxUrl = (\n chainId?: number,\n txHash?: string | null,\n ...candidates: unknown[]\n) => {\n if (!chainId || !txHash) return null;\n const baseUrl = getExplorerBaseUrl(chainId, ...candidates);\n return baseUrl ? `${String(baseUrl).replace(/\\/$/, \"\")}/tx/${txHash}` : null;\n};\n\nconst getSdkSwapResult = (result: any) => {\n const candidate = result?.swapResult ?? result?.result;\n return candidate && typeof candidate === \"object\" ? candidate : null;\n};\n\nconst getSdkTransactionHash = (result: any) =>\n getObjectTransactionHash(result) ||\n getObjectTransactionHash(result?.executeResponse) ||\n getObjectTransactionHash(result?.execute) ||\n getObjectTransactionHash(result?.transfer) ||\n getObjectTransactionHash(result?.swapResult) ||\n getObjectTransactionHash(result?.result) ||\n null;\n\nconst getSdkExplorerUrl = (result: any) =>\n getNonEmptyString(\n result?.explorerUrl,\n result?.explorerURL,\n result?.txExplorerUrl,\n result?.transactionExplorerUrl,\n result?.execute?.explorerUrl,\n result?.execute?.explorerURL,\n result?.execute?.txExplorerUrl,\n result?.execute?.transactionExplorerUrl,\n result?.executeResponse?.explorerUrl,\n result?.executeResponse?.explorerURL,\n result?.executeResponse?.txExplorerUrl,\n result?.executeResponse?.transactionExplorerUrl,\n result?.executeExplorerUrl,\n result?.transferExplorerUrl,\n result?.swapResult?.explorerUrl,\n result?.swapResult?.explorerURL,\n result?.swapResult?.txExplorerUrl,\n result?.swapResult?.transactionExplorerUrl,\n result?.result?.explorerUrl,\n result?.result?.explorerURL,\n result?.result?.txExplorerUrl,\n result?.result?.transactionExplorerUrl,\n );\n\nconst getSdkIntentExplorerUrl = (result: any, swapResult?: any) =>\n getNonEmptyString(\n swapResult?.intentExplorerUrl,\n swapResult?.intentExplorerURL,\n swapResult?.intentUrl,\n swapResult?.intentURL,\n swapResult?.rffUrl,\n swapResult?.rffURL,\n swapResult?.rffExplorerUrl,\n swapResult?.rffExplorerURL,\n swapResult?.explorerUrl,\n swapResult?.explorerURL,\n result?.intentExplorerUrl,\n result?.intentExplorerURL,\n result?.intentUrl,\n result?.intentURL,\n result?.rffUrl,\n result?.rffURL,\n result?.rffExplorerUrl,\n result?.rffExplorerURL,\n result?.swapResult?.intentExplorerUrl,\n result?.swapResult?.intentExplorerURL,\n result?.swapResult?.intentUrl,\n result?.swapResult?.intentURL,\n result?.swapResult?.rffUrl,\n result?.swapResult?.rffURL,\n result?.swapResult?.rffExplorerUrl,\n result?.swapResult?.rffExplorerURL,\n result?.swapResult?.explorerUrl,\n result?.swapResult?.explorerURL,\n result?.result?.intentExplorerUrl,\n result?.result?.intentExplorerURL,\n result?.result?.intentUrl,\n result?.result?.intentURL,\n result?.result?.rffUrl,\n result?.result?.rffURL,\n result?.result?.rffExplorerUrl,\n result?.result?.rffExplorerURL,\n result?.result?.explorerUrl,\n result?.result?.explorerURL,\n );\n\nconst getSdkIntentExplorerUrlForNetwork = (\n network: unknown,\n result: any,\n swapResult?: any,\n) =>\n getSdkIntentExplorerUrl(result, swapResult) ||\n getRffExplorerUrl(\n network,\n getObjectIntentHash(swapResult) || getObjectIntentHash(result),\n );\n\nfunction MiniLogo({\n src,\n label,\n size = 30,\n fontSize = 13,\n outline,\n style,\n}: {\n src?: string;\n label?: string;\n size?: number;\n fontSize?: number;\n outline?: string;\n style?: React.CSSProperties;\n}) {\n const [failed, setFailed] = useState(!src);\n\n useEffect(() => {\n setFailed(!src);\n }, [src]);\n\n if (!failed && src) {\n return (\n setFailed(true)}\n src={src}\n style={{\n background: \"var(--nexus-widget-surface, #FFFFFE)\",\n borderRadius: \"999px\",\n height: size,\n objectFit: \"cover\",\n outline,\n width: size,\n ...style,\n }}\n />\n );\n }\n\n return (\n \n {(label || \"?\").trim().slice(0, 1).toUpperCase()}\n \n );\n}\n\nfunction TokenLogoPair({\n tokenLogo,\n chainLogo,\n tokenSymbol,\n chainName,\n tokenOutline,\n size = 34,\n}: {\n tokenLogo?: string;\n chainLogo?: string;\n tokenSymbol?: string;\n chainName?: string;\n tokenOutline?: string;\n size?: number;\n}) {\n return (\n \n \n {chainLogo && (\n \n )}\n \n );\n}\n\nfunction SourceLogoStack({\n sources,\n size = 24,\n maxVisible = 3,\n}: {\n sources: HistorySourceRow[];\n size?: number;\n maxVisible?: number;\n}) {\n const visibleSources = sources.slice(0, maxVisible);\n const hiddenCount = Math.max(0, sources.length - visibleSources.length);\n\n return (\n \n {visibleSources.map((source, index) => (\n \n \n \n ))}\n {hiddenCount > 0 && (\n \n +{hiddenCount}\n \n )}\n \n );\n}\n\nfunction TruncatedAddress({\n address,\n color = \"var(--foreground-brand)\",\n}: {\n address: string;\n color?: string;\n}) {\n const [showTooltip, setShowTooltip] = useState(false);\n const label =\n address.length > 12\n ? `${address.slice(0, 6)}...${address.slice(-4)}`\n : address;\n\n return (\n setShowTooltip(false)}\n onFocus={() => setShowTooltip(true)}\n onMouseEnter={() => setShowTooltip(true)}\n onMouseLeave={() => setShowTooltip(false)}\n style={{\n color,\n display: \"inline-flex\",\n fontFamily: uiFont,\n fontSize: \"15px\",\n fontWeight: 500,\n lineHeight: \"20px\",\n outline: \"none\",\n position: \"relative\",\n }}\n tabIndex={0}\n >\n {label}\n {showTooltip && (\n \n {address}\n \n )}\n \n );\n}\n\nconst getDisplayDestinationSourceRow = (\n entry: SwapHistoryEntry,\n): HistorySourceRow | null => {\n if (entry.mode !== \"deposit\" && entry.mode !== \"send\") return null;\n if (!entry.toToken || !entry.requestedToAmount) return null;\n\n const requestedAmount = parseDecimalLoose(entry.requestedToAmount);\n const intentDestinationAmount = parseDecimalLoose(\n entry.intentData?.destination.amount,\n );\n const destinationBalanceAmount = parseDecimalLoose(\n entry.toToken.balance?.replace(entry.toToken.symbol, \"\"),\n );\n if (\n !requestedAmount ||\n !destinationBalanceAmount ||\n requestedAmount.lte(0) ||\n destinationBalanceAmount.lte(0)\n ) {\n return null;\n }\n\n const intentCoversAmount = intentDestinationAmount ?? new Decimal(0);\n const displayAmount = Decimal.min(\n destinationBalanceAmount,\n Decimal.max(0, requestedAmount.minus(intentCoversAmount)),\n );\n if (displayAmount.lte(0)) return null;\n\n const requestedValue = parseDecimalLoose(entry.requestedToValue);\n const destinationValue = parseDecimalLoose(\n entry.intentData?.destination.value,\n );\n const rate =\n requestedValue && requestedAmount.gt(0)\n ? requestedValue.div(requestedAmount)\n : destinationValue && intentCoversAmount.gt(0)\n ? destinationValue.div(intentCoversAmount)\n : undefined;\n\n return {\n key: `destination-balance-${entry.toToken.chainId}-${entry.toToken.contractAddress}`,\n chainId: entry.toToken.chainId,\n contractAddress: entry.toToken.contractAddress,\n tokenLogo: entry.intentData?.destination.token.logo || entry.toToken.logo,\n chainLogo: entry.toToken.chainLogo,\n symbol: entry.toToken.symbol,\n chainName: getShortChainName(\n entry.toToken.chainId,\n entry.toToken.chainName,\n ),\n amount: displayAmount\n .toDecimalPlaces(\n Math.max(0, entry.toToken.decimals ?? 18),\n Decimal.ROUND_DOWN,\n )\n .toFixed(),\n value: rate\n ? displayAmount.mul(rate).toFixed()\n : entry.toToken.balanceInFiat,\n };\n};\n\nconst getHistorySourceRowMergeKey = (row: HistorySourceRow) => {\n const chainKey = row.chainId ?? row.chainName;\n const address = row.contractAddress?.toLowerCase();\n return address\n ? `${chainKey}:${address}`\n : `${chainKey}:symbol:${row.symbol.toUpperCase()}`;\n};\n\nconst mergeHistorySourceRows = (rows: HistorySourceRow[]) => {\n const merged = new Map();\n\n for (const row of rows) {\n const key = getHistorySourceRowMergeKey(row);\n const existing = merged.get(key);\n if (!existing) {\n merged.set(key, row);\n continue;\n }\n\n merged.set(key, {\n ...existing,\n amount: sumDecimalStrings(existing.amount, row.amount) ?? existing.amount,\n chainLogo: existing.chainLogo || row.chainLogo,\n key: existing.key,\n tokenLogo: existing.tokenLogo || row.tokenLogo,\n value: sumDecimalStrings(\n String(existing.value ?? \"\"),\n String(row.value ?? \"\"),\n ),\n });\n }\n\n return Array.from(merged.values());\n};\n\nconst getProgressStepType = (step?: SwapStepType | BridgeStepType | null) =>\n String((step as any)?.type ?? (step as any)?.typeID ?? \"\").toUpperCase();\n\nconst isSourceMovementProgressStep = (type: string, rawStepType: string) =>\n rawStepType === \"source_swap\" ||\n rawStepType === \"eoa_to_ephemeral_transfer\" ||\n rawStepType === \"bridge_deposit\" ||\n rawStepType === \"vault_deposit\" ||\n type.includes(\"SOURCE_SWAP\") ||\n type.includes(\"EOA_TO_EPHEMERAL_TRANSFER\") ||\n type.includes(\"BRIDGE_DEPOSIT\") ||\n type.includes(\"VAULT_DEPOSIT\");\n\nconst isBridgeRefundStepType = (type: string) =>\n type.includes(\"BRIDGE_INTENT_SUBMISSION\") || type.includes(\"BRIDGE_DEPOSIT\");\n\nconst isSwapSkippedStepType = (type: string) => type.includes(\"SWAP_SKIPPED\");\n\nconst isAutoRefundAvailableProgressEvent = (event?: NexusWidgetProgressEvent) =>\n event?.name === PROGRESS_EVENT_NAMES.SWAP_PLAN_PROGRESS &&\n isBridgeRefundStepType(getProgressStepType(event.step));\n\nconst normalizeBridgeProvider = (\n value: unknown,\n): BridgeProvider | undefined => {\n if (value === \"nexus\" || value === \"mayan\" || value === null) {\n return value;\n }\n return undefined;\n};\n\nconst normalizePlanStepType = (stepType: unknown, state?: unknown) => {\n const normalized = String(stepType ?? \"\").toLowerCase();\n const normalizedState = String(state ?? \"\").toLowerCase();\n\n if (normalized === \"execute_transaction\") {\n return normalizedState === \"confirmed\" || normalizedState === \"completed\"\n ? \"TRANSACTION_CONFIRMED\"\n : \"TRANSACTION_SENT\";\n }\n\n const mapped: Record = {\n allowance: \"ALLOWANCE\",\n allowance_approval: \"ALLOWANCE_APPROVAL\",\n bridge_deposit: \"BRIDGE_DEPOSIT\",\n bridge_fill: \"BRIDGE_FILL\",\n bridge_intent_submission: \"BRIDGE_INTENT_SUBMISSION\",\n destination_swap: \"DESTINATION_SWAP\",\n eoa_to_ephemeral_transfer: \"EOA_TO_EPHEMERAL_TRANSFER\",\n execute_approval: \"APPROVAL\",\n request_signing: \"REQUEST_SIGNING\",\n request_submission: \"REQUEST_SUBMISSION\",\n source_swap: \"SOURCE_SWAP\",\n vault_deposit: \"BRIDGE_DEPOSIT\",\n };\n\n return mapped[normalized] ?? normalized.toUpperCase();\n};\n\nconst normalizePlanStep = (\n stepLike: unknown,\n fallbackStepType?: unknown,\n state?: unknown,\n completed?: boolean,\n): SwapStepType | BridgeStepType => {\n const source =\n stepLike && typeof stepLike === \"object\" ? (stepLike as any) : {};\n const rawStepType = fallbackStepType ?? source.stepType ?? source.type;\n const progressType = normalizePlanStepType(\n rawStepType ?? source.typeID,\n state,\n );\n const progressKey =\n source.id ?? source.stepId ?? source.typeID ?? progressType;\n\n return {\n ...source,\n completed,\n rawType: rawStepType,\n type: progressType,\n typeID: String(progressKey),\n } as SwapStepType | BridgeStepType;\n};\n\nconst getPlanStepChainId = (event: any, step: any) =>\n getObjectChainId(event) ?? getObjectChainId(step);\n\nconst getPlanStepTransactionHash = (event: any, step: any) =>\n getObjectTransactionHash(event) ?? getObjectTransactionHash(step);\n\nconst getPlanStepExplorerUrl = (event: any, step: any) => {\n const directExplorerUrl = getNonEmptyString(\n event?.explorerUrl,\n event?.explorerURL,\n event?.txExplorerUrl,\n event?.transactionExplorerUrl,\n step?.explorerUrl,\n step?.explorerURL,\n step?.txExplorerUrl,\n step?.transactionExplorerUrl,\n step?.data?.explorerUrl,\n step?.data?.explorerURL,\n step?.data?.txExplorerUrl,\n step?.data?.transactionExplorerUrl,\n );\n if (directExplorerUrl) return directExplorerUrl;\n\n return getExplorerTxUrl(\n getPlanStepChainId(event, step),\n getPlanStepTransactionHash(event, step),\n event,\n step,\n );\n};\n\nconst getPlanStepIntentExplorerUrl = (event: any, step: any) =>\n getNonEmptyString(\n event?.intentExplorerUrl,\n event?.intentExplorerURL,\n event?.intentUrl,\n event?.intentURL,\n event?.rffUrl,\n event?.rffURL,\n event?.rffExplorerUrl,\n event?.rffExplorerURL,\n step?.intentExplorerUrl,\n step?.intentExplorerURL,\n step?.intentUrl,\n step?.intentURL,\n step?.rffUrl,\n step?.rffURL,\n step?.rffExplorerUrl,\n step?.rffExplorerURL,\n step?.data?.intentExplorerUrl,\n step?.data?.intentExplorerURL,\n step?.data?.intentUrl,\n step?.data?.intentURL,\n step?.data?.rffUrl,\n step?.data?.rffURL,\n step?.data?.rffExplorerUrl,\n step?.data?.rffExplorerURL,\n );\n\nconst isIntentSubmissionLikeEvent = (event: any, step?: any) => {\n const text = [\n event?.type,\n event?.event,\n event?.name,\n event?.status,\n event?.stepType,\n step?.type,\n step?.typeID,\n step?.rawType,\n ]\n .filter((value) => value !== null && value !== undefined)\n .join(\" \")\n .toLowerCase();\n\n return (\n text.includes(\"intent\") ||\n text.includes(\"request_submission\") ||\n text.includes(\"rff\")\n );\n};\n\nconst getGenericEventHash = (event: any, step?: any) =>\n getTransactionHash(\n event?.hash,\n event?.data?.hash,\n event?.result?.hash,\n step?.hash,\n step?.data?.hash,\n step?.result?.hash,\n );\n\nconst getEventIntentExplorerUrl = (\n network: unknown,\n event: any,\n step?: any,\n) => {\n const directUrl = step\n ? getPlanStepIntentExplorerUrl(event, step)\n : getNonEmptyString(\n event?.intentExplorerUrl,\n event?.intentExplorerURL,\n event?.intentUrl,\n event?.intentURL,\n event?.rffUrl,\n event?.rffURL,\n event?.rffExplorerUrl,\n event?.rffExplorerURL,\n event?.data?.intentExplorerUrl,\n event?.data?.intentExplorerURL,\n event?.data?.intentUrl,\n event?.data?.intentURL,\n event?.data?.rffUrl,\n event?.data?.rffURL,\n event?.data?.rffExplorerUrl,\n event?.data?.rffExplorerURL,\n );\n if (directUrl) return directUrl;\n\n return getRffExplorerUrl(\n network,\n getObjectIntentHash(event) ||\n getObjectIntentHash(step) ||\n (isIntentSubmissionLikeEvent(event, step)\n ? getGenericEventHash(event, step)\n : null),\n );\n};\n\nconst isTimeoutLikeError = (error: unknown) => {\n const err = error as {\n code?: unknown;\n name?: unknown;\n message?: unknown;\n shortMessage?: unknown;\n };\n const text = [\n err?.code,\n err?.name,\n err?.message,\n err?.shortMessage,\n typeof error === \"string\" ? error : undefined,\n ]\n .filter((value) => value !== null && value !== undefined)\n .join(\" \");\n\n return /timeout|timed out|time out|deadline exceeded|expired while waiting|wait.*expired|poll.*expired/i.test(\n text,\n );\n};\n\nconst getSdkEventType = (event: any) =>\n event?.type ?? event?.name ?? event?.event ?? \"unknown\";\n\nconst summarizeSdkProgressStep = (\n step: SwapStepType | BridgeStepType | null | undefined,\n index?: number,\n) => ({\n completed: (step as any)?.completed,\n index,\n rawType: (step as any)?.rawType ?? (step as any)?.stepType,\n state: (step as any)?.state,\n type: getProgressStepType(step),\n});\n\nconst isNexusWidgetSdkDebugEnabled = () => {\n if (typeof window === \"undefined\") return false;\n if ((window as any).__NEXUS_WIDGET_DEBUG__ === true) return true;\n try {\n return window.localStorage.getItem(\"nexus-widget:debug\") === \"true\";\n } catch {\n return false;\n }\n};\n\nconst logSdkSwapEvent = (\n label: string,\n event: any,\n meta?: Record,\n) => {\n if (!isNexusWidgetSdkDebugEnabled()) return;\n console.log(`[NexusWidget SDK][swap] ${label}`, {\n event,\n eventType: getSdkEventType(event),\n ...meta,\n });\n};\n\nconst logSdkIntentEvent = (\n label: string,\n data: any,\n meta?: Record,\n) => {\n if (!isNexusWidgetSdkDebugEnabled()) return;\n console.log(`[NexusWidget SDK][intent] ${label}`, {\n hasAllow: typeof data?.allow === \"function\",\n hasDeny: typeof data?.deny === \"function\",\n hasRefresh: typeof data?.refresh === \"function\",\n intent: data?.intent,\n raw: data,\n ...meta,\n });\n};\n\nconst logSdkIntentInput = (\n operation: string,\n input: unknown,\n meta?: Record,\n) => {\n if (!isNexusWidgetSdkDebugEnabled()) return;\n console.log(`[NexusWidget SDK][intent input] ${operation}`, {\n input,\n ...meta,\n });\n};\n\nconst normalizeSdkIntentString = (value: unknown) => {\n if (value === null || value === undefined || value === \"\") return undefined;\n return String(value);\n};\n\nconst normalizeSdkIntentAmount = (value: unknown, fallback: string = \"0\") =>\n normalizeSdkIntentString(value) ?? fallback;\n\nconst getLogoFromMetadata = (metadata: any) =>\n metadata?.logo ??\n metadata?.logoURI ??\n metadata?.logoUri ??\n metadata?.logoUrl ??\n metadata?.icon ??\n \"\";\n\nconst normalizeSdkIntentChain = (chain: any) => {\n const id = Number(chain?.id ?? chain?.chainId);\n if (!Number.isFinite(id)) return undefined;\n const chainMeta = CHAIN_METADATA[id];\n return {\n id,\n logo: getLogoFromMetadata(chain) || chainMeta?.logo || \"\",\n name: chain?.name ?? chainMeta?.name ?? \"\",\n };\n};\n\nconst normalizeSdkIntentToken = (token: any, chainId?: number) => {\n const chainMeta = chainId ? CHAIN_METADATA[chainId] : undefined;\n const decimals = Number(\n token?.decimals ?? chainMeta?.nativeCurrency.decimals,\n );\n return {\n contractAddress:\n token?.contractAddress ??\n token?.address ??\n token?.tokenAddress ??\n zeroAddress,\n decimals: Number.isFinite(decimals) ? decimals : 18,\n logo: getLogoFromMetadata(token) || undefined,\n symbol: token?.symbol ?? token?.tokenSymbol ?? \"\",\n };\n};\n\nconst normalizeSdkIntentGas = (\n gas: any,\n chainId?: number,\n): SwapIntentDestination[\"gas\"] => ({\n amount: normalizeSdkIntentAmount(gas?.amount),\n value: normalizeSdkIntentString(gas?.value),\n token: normalizeSdkIntentToken(gas?.token ?? gas, chainId),\n});\n\nconst normalizeSdkIntentSource = (\n source: any,\n): SwapIntentSource | undefined => {\n const chain = normalizeSdkIntentChain(source?.chain);\n if (!chain) return undefined;\n return {\n ...source,\n amount: normalizeSdkIntentAmount(source?.amount),\n chain,\n token: normalizeSdkIntentToken(source?.token, chain.id),\n value: normalizeSdkIntentString(source?.value),\n };\n};\n\nconst normalizeSdkIntentDestination = (\n destination: any,\n): SwapIntentDestination | undefined => {\n const chain = normalizeSdkIntentChain(destination?.chain);\n if (!chain) return undefined;\n return {\n ...destination,\n amount: normalizeSdkIntentAmount(destination?.amount),\n chain,\n gas: normalizeSdkIntentGas(destination?.gas, chain.id),\n token: normalizeSdkIntentToken(destination?.token, chain.id),\n value: normalizeSdkIntentString(destination?.value),\n };\n};\n\nconst normalizeSwapIntentData = (intent: any): SwapIntentData | null => {\n const destination = normalizeSdkIntentDestination(intent?.destination);\n if (!destination) return null;\n\n return {\n ...intent,\n destination,\n sources: Array.isArray(intent?.sources)\n ? intent.sources\n .map(normalizeSdkIntentSource)\n .filter(\n (\n source: SwapIntentSource | undefined,\n ): source is SwapIntentSource => Boolean(source),\n )\n : [],\n };\n};\n\nconst normalizeSwapAndExecuteRequirementIntent = (\n intent: any,\n): SwapIntentData | null => {\n const requirement =\n intent?.executeRequirement ?? intent?.executionRequirement;\n if (!requirement) return null;\n const destination = normalizeSdkIntentDestination({\n amount: requirement?.token?.amount,\n chain: requirement?.chain,\n gas: requirement?.gas,\n token: requirement?.token,\n value: requirement?.token?.value,\n });\n if (!destination) return null;\n\n return {\n ...intent,\n bridgeProvider: normalizeBridgeProvider(intent?.bridgeProvider),\n destination,\n feesAndBuffer: intent?.feesAndBuffer,\n sources: [],\n };\n};\n\nconst normalizeRenderableSwapIntentData = (\n rawIntent: any,\n bridgeProvider?: BridgeProvider,\n): SwapIntentData | null => {\n const direct = normalizeSwapIntentData(rawIntent);\n const normalizedIntent = direct\n ? null\n : normalizeSwapIntentData(rawIntent?.normalizedIntent);\n const nestedSwap =\n direct || normalizedIntent\n ? null\n : normalizeSwapIntentData(rawIntent?.swap);\n const requirement =\n direct || normalizedIntent || nestedSwap\n ? null\n : normalizeSwapAndExecuteRequirementIntent(rawIntent);\n const normalized = direct ?? normalizedIntent ?? nestedSwap ?? requirement;\n if (!normalized) return null;\n\n return bridgeProvider === undefined\n ? normalized\n : { ...normalized, bridgeProvider };\n};\n\nconst logSwapPlanSteps = (\n eventType: \"plan_preview\" | \"plan_confirmed\",\n stepList: Array,\n rawSteps: unknown,\n) => {\n if (!isNexusWidgetSdkDebugEnabled()) return;\n console.log(`[NexusWidget SDK][swap] ${eventType} step list`, {\n count: stepList.length,\n eventType,\n rawSteps,\n steps: stepList.map((step, index) => summarizeSdkProgressStep(step, index)),\n });\n};\n\nconst logSwapPlanProgress = (\n event: any,\n step: SwapStepType | BridgeStepType,\n eventName: string,\n completed: boolean,\n) => {\n if (!isNexusWidgetSdkDebugEnabled()) return;\n console.log(\"[NexusWidget SDK][swap] plan_progress\", {\n completed,\n eventName,\n eventType: getSdkEventType(event),\n normalizedStep: summarizeSdkProgressStep(step),\n rawEvent: event,\n rawStep: event?.step,\n state: event?.state,\n stepType: event?.stepType,\n });\n};\n\nconst getFailureMessageForProgressStep = (\n step: SwapStepType | BridgeStepType | null | undefined,\n mode: NexusWidgetMode,\n autoRefundAvailable = false,\n) => {\n if (autoRefundAvailable) {\n return \"Swap Failed. Refund Initiated\";\n }\n\n const type = getProgressStepType(step);\n if (\n type.includes(\"CREATE_PERMIT_FOR_SOURCE_SWAP\") ||\n type.includes(\"CREATE_PERMIT_EOA_TO_EPHEMERAL\") ||\n type.includes(\"EOA_EXECUTE_CALL\") ||\n type.includes(\"SOURCE_SWAP\") ||\n type.includes(\"COLLECTION\")\n ) {\n return \"Collection Failed\";\n }\n if (type.includes(\"DESTINATION_SWAP\") || type.includes(\"FULFIL\")) {\n return \"Destination Swap Failed\";\n }\n if (\n type.includes(\"TRANSACTION\") ||\n type.includes(\"APPROVAL\") ||\n type.includes(\"DEPOSIT\")\n ) {\n return mode === \"send\"\n ? \"Send failed. Funds are in your wallet\"\n : mode === \"deposit\"\n ? \"Deposit failed. Funds are in your wallet\"\n : \"Swap Failed\";\n }\n if (\n type.includes(\"SWAP\") ||\n type.includes(\"BRIDGE\") ||\n type.includes(\"INTENT\") ||\n type.includes(\"DETERMINING\")\n ) {\n return \"Swap Failed\";\n }\n return mode === \"send\"\n ? \"Send failed. Funds are in your wallet\"\n : mode === \"deposit\"\n ? \"Deposit failed. Funds are in your wallet\"\n : \"Swap Failed\";\n};\n\nconst getBridgeTokenSymbolForProgressStep = (\n step: SwapStepType | BridgeStepType | null | undefined,\n) => {\n const rawStep = step as any;\n return (\n getNonEmptyString(\n rawStep?.bridgeToken?.symbol,\n rawStep?.data?.bridgeToken?.symbol,\n rawStep?.bridgeTokenSymbol,\n rawStep?.data?.bridgeTokenSymbol,\n rawStep?.swaps?.[0]?.input?.symbol,\n rawStep?.data?.swaps?.[0]?.input?.symbol,\n rawStep?.input?.symbol,\n rawStep?.data?.input?.symbol,\n rawStep?.asset?.symbol,\n rawStep?.data?.asset?.symbol,\n ) ?? \"USDC\"\n );\n};\n\nconst getFailureDescriptionForProgressStep = (\n step: SwapStepType | BridgeStepType | null | undefined,\n autoRefundAvailable = false,\n) => {\n if (autoRefundAvailable) return undefined;\n const type = getProgressStepType(step);\n if (!type.includes(\"DESTINATION_SWAP\")) return undefined;\n const bridgeTokenSymbol = getBridgeTokenSymbolForProgressStep(step);\n return `${bridgeTokenSymbol} has been bridged and you have those funds in your wallet.`;\n};\n\nconst getSourceRows = (entry: SwapHistoryEntry): HistorySourceRow[] => {\n const sources = entry.intentData?.sources ?? [];\n const displayDestinationSourceRow = getDisplayDestinationSourceRow(entry);\n if (sources.length > 0) {\n const sourceRows = sources.map((source, index) => {\n const fallback = entry.fromTokens.find(\n (token) =>\n token.chainId === source.chain.id &&\n (token.contractAddress?.toLowerCase() ===\n source.token.contractAddress?.toLowerCase() ||\n token.symbol === source.token.symbol),\n );\n\n return {\n key: `${source.chain.id}-${source.token.contractAddress}-${index}`,\n chainId: source.chain.id,\n contractAddress: source.token.contractAddress,\n tokenLogo: source.token.logo || fallback?.logo,\n chainLogo: source.chain.logo || fallback?.chainLogo,\n symbol: source.token.symbol,\n chainName: getShortChainName(source.chain.id, source.chain.name),\n amount: source.amount,\n value: source.value,\n };\n });\n\n return mergeHistorySourceRows(\n displayDestinationSourceRow\n ? [displayDestinationSourceRow, ...sourceRows]\n : sourceRows,\n );\n }\n\n const fallbackRows = entry.fromTokens.map((token, index) => ({\n key: `${token.chainId}-${token.contractAddress}-${index}`,\n chainId: token.chainId,\n contractAddress: token.contractAddress,\n tokenLogo: token.logo,\n chainLogo: token.chainLogo,\n symbol: token.symbol,\n chainName: getShortChainName(token.chainId, token.chainName),\n amount: token.userAmount || \"0\",\n value: token.balanceInFiat,\n }));\n\n return mergeHistorySourceRows(\n displayDestinationSourceRow\n ? [displayDestinationSourceRow, ...fallbackRows]\n : fallbackRows,\n );\n};\n\nfunction SourceRowsList({\n entry,\n maxHeight = 236,\n borderTopFirst = true,\n scrollAfterRows = 4,\n}: {\n entry: SwapHistoryEntry;\n maxHeight?: number;\n borderTopFirst?: boolean;\n scrollAfterRows?: number;\n}) {\n const rows = getSourceRows(entry);\n const shouldScroll = rows.length > scrollAfterRows;\n const scrollRef = useRef(null);\n\n return (\n
\n \n {rows.map((row, index) => (\n 0\n ? \"1px solid var(--nexus-widget-border, #E8E8E7)\"\n : \"none\",\n display: \"flex\",\n justifyContent: \"space-between\",\n minHeight: \"64px\",\n padding: \"10px 20px\",\n }}\n >\n \n \n
\n \n {row.symbol}\n \n \n on {row.chainName || \"Unknown chain\"}\n \n
\n
\n \n \n {formatTokenDisplay(row.amount)} {row.symbol}\n \n \n {formatUsdDisplay(row.value)}\n \n \n \n ))}\n \n {shouldScroll && (\n \n scrollRef.current?.scrollBy({ top: 72, behavior: \"smooth\" })\n }\n style={{\n alignItems: \"center\",\n background: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: \"1px solid var(--nexus-widget-border, #E8E8E7)\",\n borderRadius: \"999px\",\n bottom: \"6px\",\n boxShadow:\n \"0 2px 8px var(--nexus-widget-shadow-soft, rgba(22,22,21,0.08))\",\n display: \"flex\",\n height: \"22px\",\n justifyContent: \"center\",\n left: \"50%\",\n padding: 0,\n position: \"absolute\",\n transform: \"translateX(-50%)\",\n width: \"22px\",\n }}\n type=\"button\"\n >\n \n \n )}\n \n );\n}\n\nfunction SwapReceiptPanel({\n entry,\n onDone,\n}: {\n entry: SwapHistoryEntry;\n onDone: () => void;\n}) {\n const [showSourceDetails, setShowSourceDetails] = useState(false);\n const destination = entry.intentData?.destination;\n const isFailed = entry.status === \"failed\";\n const isTimeout = entry.status === \"timeout\";\n const isDeposit = entry.mode === \"deposit\";\n const isSend = entry.mode === \"send\";\n const isRecipientTransfer = isSend || Boolean(entry.recipientAddress);\n const tokenSymbol = destination?.token.symbol || entry.toToken?.symbol || \"\";\n const chainName = getShortChainName(\n destination?.chain.id ?? entry.toToken?.chainId,\n destination?.chain.name || entry.toToken?.chainName || \"\",\n );\n const depositVenue =\n entry.opportunity?.title || entry.opportunity?.protocol || chainName;\n const amount = destination?.amount || \"\";\n const destinationLogo =\n destination?.token.logo ||\n entry.toToken?.logo ||\n entry.opportunity?.tokenLogo ||\n (isDeposit ? entry.opportunity?.logo : undefined);\n const requestedExactOutAmount =\n (isDeposit || isSend) && entry.requestedToAmount\n ? entry.requestedToAmount\n : undefined;\n const requestedExactOutValue =\n (isDeposit || isSend) && entry.requestedToValue\n ? entry.requestedToValue\n : undefined;\n const value = requestedExactOutValue || destination?.value;\n const displayAmount = requestedExactOutAmount || amount;\n const showIntentExplorer = hasValidIntentExplorer(entry);\n const intentLabel = entry.intentId\n ? `Intent #${entry.intentId}`\n : \"View Explorer\";\n const sourceRows = getSourceRows(entry);\n const sourceCount = sourceRows.length;\n const sourceTotalUsd = sourceRows.reduce(\n (sum, source) => sum.plus(parseDecimalLoose(source.value) ?? 0),\n new Decimal(0),\n );\n const defaultSwapFailureHeadline = entry.autoRefundAvailable\n ? \"Swap Failed. Refund Initiated\"\n : \"Swap Failed\";\n const entryFailureMessage =\n entry.status === \"timeout\" ? TIMEOUT_LABEL : entry.failureMessage;\n const storedFailureMessage =\n !entry.autoRefundAvailable && entryFailureMessage?.includes(\"Refund\")\n ? undefined\n : entryFailureMessage;\n const failureHeadline =\n storedFailureMessage ||\n (isDeposit\n ? \"Deposit failed. Funds are in your wallet\"\n : isRecipientTransfer\n ? \"Send failed. Funds are in your wallet\"\n : defaultSwapFailureHeadline);\n const failureDescription = isFailed ? entry.failureDescription : undefined;\n const timeoutHeadline = TIMEOUT_LABEL;\n const timeoutDescription = isTimeout\n ? entry.failureDescription ||\n \"This transaction is still pending. Check the intent explorer for the latest status.\"\n : undefined;\n const receiptLocation = isDeposit ? depositVenue : chainName;\n const receiptSummary = receiptLocation ? `on ${receiptLocation}` : \"\";\n\n return (\n \n \n \n \n \n {isFailed ? \"x\" : isTimeout ? \"!\" : \"✓\"}\n \n \n \n {isTimeout\n ? timeoutHeadline\n : isFailed\n ? failureHeadline\n : isDeposit\n ? \"You deposited\"\n : isRecipientTransfer\n ? \"You sent\"\n : \"You received\"}\n \n {(failureDescription || timeoutDescription) && (\n \n {failureDescription || timeoutDescription}\n \n )}\n \n {displayAmount ? formatTokenDisplay(displayAmount) : \"--\"}\n \n {tokenSymbol}\n \n \n \n ≈ {formatUsdDisplay(value)}\n \n {receiptSummary && (\n \n {receiptSummary}\n \n )}\n \n\n \n \n \n {isDeposit || isSend ? \"You Paid\" : \"You Swapped\"}\n \n \n \n {formatUsdDisplay(sourceTotalUsd)}\n \n setShowSourceDetails((current) => !current)}\n style={{\n alignItems: \"center\",\n background: \"transparent\",\n border: \"none\",\n color: \"var(--foreground-brand)\",\n cursor: \"pointer\",\n display: \"inline-flex\",\n fontFamily: uiFont,\n fontSize: \"12px\",\n gap: \"4px\",\n padding: 0,\n }}\n type=\"button\"\n >\n {showSourceDetails\n ? \"Hide Details\"\n : `${sourceCount} asset${sourceCount === 1 ? \"\" : \"s\"}`}\n \n \n \n \n \n
\n \n
\n \n {isRecipientTransfer && entry.recipientAddress && (\n \n \n Recipient\n \n \n \n )}\n {showIntentExplorer && (\n \n \n Intent Explorer\n \n \n {intentLabel} ↗\n \n \n )}\n {entry.finalExplorerUrl && (\n \n \n Final Transaction\n \n \n View Explorer ↗\n \n \n )}\n \n \n Total Fees\n \n \n {formatUsdDisplay(entry.feeUsd)}\n \n \n \n\n \n Done\n \n \n );\n}\n\nconst getRelativeTime = (time: number, now: number) => {\n const seconds = Math.max(1, Math.floor((now - time) / 1000));\n if (seconds < 60) return `${seconds} second${seconds === 1 ? \"\" : \"s\"} ago`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes} minute${minutes === 1 ? \"\" : \"s\"} ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours} hour${hours === 1 ? \"\" : \"s\"} ago`;\n const days = Math.floor(hours / 24);\n return `${days} day${days === 1 ? \"\" : \"s\"} ago`;\n};\n\nfunction HistoryStatusPill({ status }: { status: SwapHistoryStatus }) {\n const config =\n status === \"fulfilled\"\n ? {\n label: \"Fulfilled\",\n bg: \"var(--nexus-widget-success-background, #E8F6EF)\",\n fg: \"var(--nexus-widget-success-text, #168A47)\",\n }\n : status === \"pending\"\n ? {\n label: \"Pending\",\n bg: \"var(--nexus-widget-warning-background, #FFF3DE)\",\n fg: \"var(--nexus-widget-warning-text, #B7791F)\",\n }\n : status === \"timeout\"\n ? {\n label: TIMEOUT_LABEL,\n bg: \"var(--nexus-widget-warning-background, #FFF3DE)\",\n fg: \"var(--nexus-widget-warning-text, #B7791F)\",\n }\n : status === \"refund-initiated\"\n ? {\n label: \"Refund Initiated\",\n bg: \"var(--nexus-widget-warning-background, #FFF3DE)\",\n fg: \"var(--nexus-widget-warning-text, #B7791F)\",\n }\n : {\n label: \"Failed\",\n bg: \"var(--nexus-widget-error-background, #FFE6EA)\",\n fg: \"var(--nexus-widget-error-text, #E92C2C)\",\n };\n\n return (\n \n {config.label}\n \n );\n}\n\nfunction SwapHistoryPanel({\n entries,\n now,\n}: {\n entries: TransactionHistoryEntry[];\n now: number;\n}) {\n if (entries.length === 0) {\n return (\n \n \n \n ↻\n \n \n \n No transactions yet\n \n \n Your transaction history will appear here once you make your first\n swap, deposit, or send.\n \n \n );\n }\n\n const sortedEntries = sortSwapHistoryEntries(entries);\n const shouldScroll = sortedEntries.length > 5;\n\n return (\n \n {sortedEntries.map((entry) => {\n if (isOnrampHistoryEntry(entry)) {\n const chainId =\n entry.session.transaction?.chainId ?? entry.context.chainId;\n const explorerBase = getExplorerBaseUrl(chainId);\n const txHash = getTransactionHash(entry.session.transaction?.txHash);\n return (\n \n );\n }\n const destination = entry.intentData?.destination;\n const destinationLogo =\n destination?.token.logo ||\n entry.toToken?.logo ||\n entry.opportunity?.tokenLogo ||\n \"\";\n const destinationChainLogo =\n destination?.chain.logo || entry.toToken?.chainLogo || \"\";\n const destinationChainName = getShortChainName(\n destination?.chain.id ?? entry.toToken?.chainId,\n destination?.chain.name || entry.toToken?.chainName || \"\",\n );\n const destinationSymbol =\n destination?.token.symbol || entry.toToken?.symbol || \"\";\n const destinationValue =\n (entry.mode === \"deposit\" || entry.mode === \"send\") &&\n entry.requestedToValue\n ? entry.requestedToValue\n : destination?.value;\n const destinationAmount =\n (entry.mode === \"deposit\" || entry.mode === \"send\") &&\n entry.requestedToAmount\n ? entry.requestedToAmount\n : destination?.amount || \"\";\n const canShowRefund =\n entry.status === \"failed\" && Boolean(entry.autoRefundAvailable);\n const status = canShowRefund ? \"refund-initiated\" : entry.status;\n const sourceRows = getSourceRows(entry);\n const historyExplorerUrl = getHistoryExplorerUrl(entry);\n\n return (\n \n \n \n \n
\n \n {destinationAmount\n ? formatTokenDisplay(destinationAmount)\n : \"--\"}\n \n {destinationSymbol}\n \n
\n \n ≈ {formatUsdDisplay(destinationValue)}\n \n \n \n \n \n \n {getRelativeTime(entry.createdAt ?? entry.startedAt, now)}\n \n \n \n\n {canShowRefund && (\n \n \n Refund Initiated\n \n \n )}\n\n \n \n {sourceRows.length > 0 && (\n \n )}\n \n →\n \n \n \n {historyExplorerUrl && (\n \n \n View\n \n \n \n \n \n \n )}\n \n \n );\n })}\n \n );\n}\n\n// ---------------------------------------------------------------------------\n// NexusWidget\n// ---------------------------------------------------------------------------\n\nexport function NexusWidget(props: NexusWidgetProps) {\n const resolvedTheme = useResolvedNexusWidgetTheme(\n resolveNexusWidgetTheme(props.config.theme, props.config.appearance?.mode),\n );\n const primaryColor =\n normalizeNexusWidgetPrimaryColor(props.config.appearance?.primaryColor) ??\n NEXUS_WIDGET_DEFAULT_PRIMARY_COLOR;\n const primaryForeground = getReadableTextColor(primaryColor);\n const themeStyle = useMemo(\n () => ({\n ...getNexusWidgetThemeStyle(resolvedTheme === \"dark\"),\n \"--nexus-widget-primary\": primaryColor,\n \"--nexus-widget-primary-foreground\": primaryForeground,\n \"--foreground-brand\": primaryColor,\n \"--interactive-button-primary-background\": primaryColor,\n \"--interactive-button-primary-foreground\": primaryForeground,\n }),\n [resolvedTheme, primaryColor, primaryForeground],\n );\n return (\n \n \n \n Something went wrong\n \n \n An unexpected error occurred. Please refresh the page or try\n resetting the widget.\n \n window.location.reload()}\n style={{\n backgroundColor: \"var(--foreground-brand)\",\n border: \"none\",\n borderRadius: \"8px\",\n color: \"var(--nexus-widget-primary-foreground, #FFFFFE)\",\n cursor: \"pointer\",\n fontSize: \"15px\",\n fontWeight: 500,\n padding: \"8px 16px\",\n transition: \"background-color 0.15s ease-out\",\n }}\n type=\"button\"\n >\n Reload Page\n \n \n }\n >\n \n \n \n );\n}\n\nfunction NexusWidgetInner({\n config: rawConfig,\n embed = true,\n className,\n connectedAddress,\n open: controlledOpen,\n onOpenChange,\n defaultOpen = false,\n onComplete,\n onConnectClick,\n onStart,\n onError,\n onReceiveAssetChange,\n onClose,\n onConnectWallet,\n}: NexusWidgetProps) {\n const themeStyle = useNexusWidgetThemeStyle();\n const {\n nexusSDK,\n bridgableBalance,\n swapBalance,\n swapBalanceLoading,\n getFiatValue,\n resolveTokenUsdRate,\n swapSupportedChainsAndTokens,\n supportedChainsAndTokens,\n fetchSwapBalance,\n handleInit,\n swapIntent: providerSwapIntent,\n network,\n loading: nexusLoading,\n } = useNexus();\n const appConfig = useMemo(\n () => ({\n nexusNetwork: network ?? \"mainnet\",\n }),\n [network],\n );\n const isSwapBalancePending =\n Boolean(nexusSDK) && (swapBalanceLoading || swapBalance === null);\n\n const normalizedWidgetConfig = useMemo(\n () => normalizeNexusWidgetConfig(rawConfig),\n [rawConfig],\n );\n const config = normalizedWidgetConfig.config;\n const activeMode = normalizedWidgetConfig.activeMode;\n const amountInputConfig = normalizedWidgetConfig.amountInput;\n const appearanceConfig = normalizedWidgetConfig.appearance;\n const configuredDepositOptions = normalizedWidgetConfig.depositOptions;\n const configuredEnableOnRamp = normalizedWidgetConfig.enableOnRamp;\n const isConfiguredAmountFixed = normalizedWidgetConfig.isAmountFixed;\n const isConfiguredRecipientLocked = normalizedWidgetConfig.isRecipientLocked;\n const primaryColor = normalizeNexusWidgetPrimaryColor(\n appearanceConfig?.primaryColor,\n );\n const primaryButtonBackground =\n primaryColor ?? NEXUS_WIDGET_DEFAULT_PRIMARY_COLOR;\n const primaryButtonForeground = getReadableTextColor(primaryButtonBackground);\n const theme = useMemo(\n () => ({\n ...nexusWidgetTheme,\n colors: {\n ...nexusWidgetTheme.colors,\n primary: \"var(--foreground-brand)\",\n primaryText: \"var(--foreground-brand)\",\n },\n }),\n [primaryColor],\n );\n const configuredDeposit = getConfiguredDeposit(config);\n const configuredDepositIdentity = getDepositConfigIdentity(configuredDeposit);\n const configuredDestinationTokenOptions = useMemo(() => {\n const destination = rawConfig.destination;\n const destinationChainId = getConfiguredDestinationChainId(destination);\n const destinationTokens =\n rawConfig.mode === \"deposit\"\n ? configuredDepositOptions.map(toSwapTokenOptionFromDepositConfig)\n : destination?.tokens && destinationChainId\n ? destination.tokens\n .map((token) =>\n toSwapTokenOptionFromConfiguredDestinationToken(\n token,\n destinationChainId,\n ),\n )\n .filter((token): token is SwapTokenOption => Boolean(token))\n : [];\n\n const tokensByKey = new Map();\n for (const token of destinationTokens) {\n tokensByKey.set(getTokenSelectionKey(token), token);\n }\n return Array.from(tokensByKey.values());\n }, [configuredDepositOptions, rawConfig.destination]);\n if (activeMode === \"deposit\" && !configuredDeposit) {\n throw new Error(\n \"NexusWidget deposit mode requires destination.chain, at least one destination token, depositAddress, and executeDeposit.\",\n );\n }\n const showCloseButton = !embed;\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isControlledOpen = controlledOpen !== undefined;\n const isModalOpen = isControlledOpen ? controlledOpen : internalOpen;\n\n // Preload receive tokens once SDK is available\n useEffect(() => {\n if (nexusSDK) {\n console.log(\n \"[preloadReceiveTokens] Calling preloadReceiveTokens from NexusWidget useEffect (nexusSDK available)\",\n );\n preloadReceiveTokens();\n }\n }, [nexusSDK]);\n\n const {\n address: accountAddress,\n connector,\n status: walletStatus,\n } = useAccount();\n const {\n connectors,\n connectAsync,\n isPending: isWalletConnectPending,\n } = useConnect();\n const { data: walletClient } = useWalletClient();\n const { disconnectAsync } = useDisconnect();\n const { data: connectorClient } = useConnectorClient();\n const publicClient = usePublicClient();\n const walletClientAddress = walletClient?.account?.address;\n const ownerAddress =\n connectedAddress &&\n isAddress(connectedAddress) &&\n connectedAddress.toLowerCase() !== zeroAddress\n ? connectedAddress\n : accountAddress &&\n isAddress(accountAddress) &&\n accountAddress.toLowerCase() !== zeroAddress\n ? accountAddress\n : walletClientAddress &&\n isAddress(walletClientAddress) &&\n walletClientAddress.toLowerCase() !== zeroAddress\n ? walletClientAddress\n : undefined;\n const getEffectiveWalletProvider = useCallback(\n async (activeConnector = connector) => {\n let connectorProvider: unknown;\n try {\n connectorProvider = await activeConnector?.getProvider();\n } catch {\n connectorProvider = undefined;\n }\n\n const connectorClientProvider = connectorClient\n ? {\n request: (args: unknown) => connectorClient.request(args as any),\n }\n : undefined;\n const walletClientProvider = walletClient\n ? {\n request: (args: unknown) => walletClient.request(args as any),\n }\n : undefined;\n const windowProvider =\n typeof window !== \"undefined\"\n ? (window as Window & { ethereum?: EthereumProvider }).ethereum\n : undefined;\n const effectiveProvider =\n connectorProvider &&\n typeof (connectorProvider as EthereumProvider).request === \"function\"\n ? (connectorProvider as EthereumProvider)\n : (connectorClientProvider ?? walletClientProvider ?? windowProvider);\n\n return effectiveProvider &&\n typeof effectiveProvider.request === \"function\"\n ? (effectiveProvider as EthereumProvider)\n : undefined;\n },\n [connector, connectorClient, walletClient],\n );\n const getOnrampWalletProvider = useCallback(async () => {\n if (walletStatus !== \"connected\" || !connector) return undefined;\n // Never substitute another injected wallet for an inactive WalletConnect session.\n const provider = await connector.getProvider();\n return provider &&\n typeof (provider as EthereumProvider).request === \"function\"\n ? (provider as EthereumProvider)\n : undefined;\n }, [connector, walletStatus]);\n const historyStorageKey = getSwapHistoryStorageKey(ownerAddress);\n\n useEffect(() => {\n if (walletStatus !== \"connected\" || !ownerAddress) {\n return;\n }\n\n let cancelled = false;\n void (async () => {\n const effectiveProvider = await getEffectiveWalletProvider();\n if (cancelled || !effectiveProvider) {\n return;\n }\n await handleInit(effectiveProvider, ownerAddress);\n })().catch((error) => {\n if (!cancelled) {\n console.error(\"Unable to initialize Nexus for wallet address:\", error);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [getEffectiveWalletProvider, handleInit, ownerAddress, walletStatus]);\n\n // Global form state\n const [amount, setAmount] = useState(\"\");\n const [recipientAddress, setRecipientAddress] = useState(\"\");\n const [editingAssetIndex, setEditingAssetIndex] = useState(\n null,\n );\n const [txError, setTxError] = useState(null);\n const [walletActionPending, setWalletActionPending] = useState(false);\n const defaultRecipientAddress = ownerAddress ?? \"\";\n const effectiveRecipientAddress =\n activeMode === \"swap\"\n ? recipientAddress || defaultRecipientAddress\n : recipientAddress;\n const hasSameOwnerSendRecipient =\n activeMode === \"send\" &&\n Boolean(\n ownerAddress &&\n recipientAddress &&\n isAddress(recipientAddress) &&\n recipientAddress.toLowerCase() === ownerAddress.toLowerCase(),\n );\n const hasCustomSwapRecipient =\n activeMode === \"swap\" &&\n Boolean(\n recipientAddress &&\n (!defaultRecipientAddress ||\n recipientAddress.toLowerCase() !==\n defaultRecipientAddress.toLowerCase()),\n );\n const transferRecipientAddress =\n activeMode === \"send\"\n ? recipientAddress\n : hasCustomSwapRecipient\n ? recipientAddress\n : undefined;\n\n // Swap-specific\n const [swapType, setSwapType] = useState(\"exactIn\");\n const [swapStep, setSwapStep] = useState(\"idle\");\n const [depositFundingStep, setDepositFundingStep] =\n useState(configuredEnableOnRamp ? \"method\" : \"wallet\");\n const [depositOnrampSessionState, setDepositOnrampSessionState] = useState<\n string | null\n >(null);\n const drawerCloseTimerRef = useRef | null>(\n null,\n );\n const terminalBalanceRefreshTimerRef = useRef | null>(null);\n const [closingDrawerStep, setClosingDrawerStep] = useState(\n null,\n );\n const rootContentRef = useRef(null);\n const [rootContentHeight, setRootContentHeight] = useState(\n null,\n );\n const rootContentHeightRef = useRef(null);\n const [hasMeasuredRootContent, setHasMeasuredRootContent] = useState(false);\n const [shouldAnimateRootHeight, setShouldAnimateRootHeight] = useState(false);\n const [isPreviewTransitioning, setIsPreviewTransitioning] = useState(false);\n const rootHeightTransitionTimerRef = useRef | null>(null);\n const [fromTokens, setFromTokens] = useState([]);\n const [sourceSelectionTouched, setSourceSelectionTouched] = useState(false);\n const [sourceSelectionRevision, setSourceSelectionRevision] = useState(0);\n const [\n sourceSelectionRequiredUsdDisplay,\n setSourceSelectionRequiredUsdDisplay,\n ] = useState(undefined);\n const [sourcePickerDraftTokens, setSourcePickerDraftTokens] = useState<\n SwapTokenOption[] | null\n >(null);\n const sourcePickerDraftTokensRef = useRef(null);\n const sourcePickerDraftDepositFilterRef = useRef(\"all\");\n const sourcePickerDraftTouchedRef = useRef(false);\n const sourcePickerDraftModeRef = useRef<\"all\" | \"selected\">(\"all\");\n const [exactOutQuoteSourceMode, setExactOutQuoteSourceMode] = useState<\n \"all\" | \"selected\"\n >(\"all\");\n const exactOutQuoteSourceModeRef = useRef<\"all\" | \"selected\">(\"all\");\n const [toToken, setToToken] = useState(\n undefined,\n );\n const [fromTokensQuoteKey, setFromTokensQuoteKey] = useState(\"\");\n\n useEffect(() => {\n setDepositFundingStep(\n activeMode === \"deposit\" && configuredEnableOnRamp ? \"method\" : \"wallet\",\n );\n }, [activeMode, configuredEnableOnRamp]);\n\n useEffect(() => {\n const key = getSourceTokensQuoteKey(\n activeMode === \"swap\" && swapType === \"exactIn\"\n ? getReadyExactInSourceTokens(fromTokens)\n : fromTokens,\n );\n setFromTokensQuoteKey(key);\n }, [activeMode, swapType, fromTokens]);\n const toTokenQuoteKey = getTokenQuoteKey(toToken);\n const appliedTokenPrefillRef = useRef(null);\n\n useEffect(() => {\n if (!toToken?.chainId || !toToken.contractAddress) return;\n\n let active = true;\n const selectedTokenKey = getTokenSelectionKey(toToken);\n const applyLoadedReceiveToken = () => {\n if (!active) return;\n const loadedToken = getCachedReceiveTokenMatch(toToken);\n if (!loadedToken) return;\n\n setToToken((current) => {\n if (!current || getTokenSelectionKey(current) !== selectedTokenKey) {\n return current;\n }\n\n const chainMeta = current.chainId\n ? CHAIN_METADATA[current.chainId]\n : undefined;\n const next = {\n ...current,\n chainLogo:\n loadedToken.chainLogo || current.chainLogo || chainMeta?.logo,\n chainName: getShortChainName(\n current.chainId,\n loadedToken.chainName || current.chainName || chainMeta?.name,\n ),\n decimals: loadedToken.decimals ?? current.decimals,\n logo: loadedToken.logo || current.logo,\n name: loadedToken.name || current.name,\n priceUSD: loadedToken.priceUSD ?? current.priceUSD,\n symbol: loadedToken.symbol || current.symbol,\n };\n\n if (\n current.decimals === next.decimals &&\n current.chainLogo === next.chainLogo &&\n current.chainName === next.chainName &&\n current.logo === next.logo &&\n current.name === next.name &&\n current.priceUSD === next.priceUSD &&\n current.symbol === next.symbol\n ) {\n return current;\n }\n\n return next;\n });\n };\n\n applyLoadedReceiveToken();\n const receiveTokensPromise = preloadReceiveTokens();\n receiveTokensPromise?.then(applyLoadedReceiveToken).catch((error) => {\n if (active) {\n console.warn(\"Unable to refresh receive token metadata\", error);\n }\n });\n\n return () => {\n active = false;\n };\n }, [\n toToken?.chainId,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.symbol,\n ]);\n\n const setExactOutQuoteSourceModeValue = useCallback(\n (mode: \"all\" | \"selected\") => {\n exactOutQuoteSourceModeRef.current = mode;\n setExactOutQuoteSourceMode(mode);\n },\n [],\n );\n\n useEffect(() => {\n if (!nexusSDK) return;\n void fetchSwapBalance();\n }, [fetchSwapBalance, nexusSDK]);\n\n useEffect(() => {\n setSourceSelectionTouched(false);\n setExactOutQuoteSourceModeValue(\"all\");\n }, [activeMode, setExactOutQuoteSourceModeValue]);\n\n useEffect(() => {\n if (activeMode !== \"swap\") return;\n\n setRecipientAddress((current) => {\n if (!defaultRecipientAddress) return current ? \"\" : current;\n return current.toLowerCase() === defaultRecipientAddress.toLowerCase()\n ? current\n : defaultRecipientAddress;\n });\n }, [activeMode, defaultRecipientAddress]);\n\n const {\n steps,\n seed,\n onStepsList,\n onStepComplete,\n reset: resetSteps,\n } = useTransactionSteps();\n const [progressEvents, setProgressEvents] = useState<\n NexusWidgetProgressEvent[]\n >([]);\n const progressEventsRef = useRef([]);\n const swapStepsListRef = useRef([]);\n const [failedProgressStep, setFailedProgressStep] = useState<\n SwapStepType | BridgeStepType | null\n >(null);\n const [explorerUrls, setExplorerUrls] = useState<{\n sourceExplorerUrl: string | null;\n destinationExplorerUrl: string | null;\n }>({ sourceExplorerUrl: null, destinationExplorerUrl: null });\n const swapRunIdRef = useRef(0);\n\n const widgetSessionIdRef = useRef(\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(36).slice(2)}`,\n );\n const widgetAttemptIdRef = useRef(null);\n const widgetOpenedTsRef = useRef(Date.now());\n const previewViewedTsRef = useRef(null);\n const previewConfirmedTsRef = useRef(null);\n const attemptCountRef = useRef(0);\n const fundsMovedRef = useRef(false);\n const intentUrlRef = useRef(null);\n const hadSimulationSuccessRef = useRef(false);\n const hadPreviewViewedRef = useRef(false);\n const widgetOpenedFiredRef = useRef(false);\n const reachedTerminalRef = useRef(false);\n const lastIntentSourceTokensRef = useRef([]);\n const lastAutoIntentSourceTokensRef = useRef([]);\n const immediateQuoteAfterSourceEditRef = useRef(false);\n const amountEnteredLastValueRef = useRef(\"\");\n const lastInputMethodRef = useRef<\n | \"typed\"\n | \"percent_20\"\n | \"percent_25\"\n | \"percent_50\"\n | \"percent_75\"\n | \"percent_max\"\n >(\"typed\");\n const prevSourceTouchedRef = useRef(false);\n const previousAutoSourceCountRef = useRef(0);\n const analyticsRef = useRef<{\n track: (event: string, properties?: Record) => void;\n } | null>(null);\n const selectedOpportunityRef = useRef<\n NexusWidgetDepositOpportunityConfig | undefined\n >(undefined);\n\n const newAttemptId = useCallback(() => {\n return typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n }, []);\n\n const rotateAttempt = useCallback(() => {\n widgetAttemptIdRef.current = newAttemptId();\n previewViewedTsRef.current = null;\n previewConfirmedTsRef.current = null;\n fundsMovedRef.current = false;\n intentUrlRef.current = null;\n hadSimulationSuccessRef.current = false;\n hadPreviewViewedRef.current = false;\n reachedTerminalRef.current = false;\n }, [newAttemptId]);\n const [intentToAmount, setIntentToAmount] = useState(\n undefined,\n );\n const [intentFeeUsd, setIntentFeeUsd] = useState(\n undefined,\n );\n const [intentLoading, setIntentLoading] = useState(false);\n const [quoteRefreshing, setQuoteRefreshing] = useState(false);\n const [receiveMaxCalculating, setReceiveMaxCalculating] = useState(false);\n const [maxCalculationPercent, setMaxCalculationPercent] = useState<\n number | null\n >(null);\n const intentDestinationUsdRateCacheRef = useRef<\n Record\n >({});\n const intentSymbolUsdRateCacheRef = useRef<\n Record\n >({});\n const predictiveQuoteCacheRef = useRef<\n Record\n >({});\n const predictiveQuoteRunRef = useRef(0);\n const latestIntentFetchRunIdRef = useRef(0);\n const intentFetchTimingRef = useRef(null);\n const intentUiRenderLoggedRunIdRef = useRef(null);\n const [intentFetchTiming, setIntentFetchTiming] =\n useState(null);\n const [predictiveQuote, setPredictiveQuote] =\n useState(null);\n const maxPercentRunRef = useRef(0);\n const [previewQuoteRefreshing, setPreviewQuoteRefreshing] = useState(false);\n const [quoteRefreshProgress, setQuoteRefreshProgress] = useState(0);\n const [quoteRefreshSecondsRemaining, setQuoteRefreshSecondsRemaining] =\n useState(0);\n const [intentData, setIntentData] = useState(null);\n const [swapQuoteIssue, setSwapQuoteIssue] = useState(\n null,\n );\n const [receiveAmountIssue, setReceiveAmountIssue] =\n useState(null);\n const receiveAmountIssueRef = useRef(null);\n const receiveAmountIssueKeyRef = useRef(\"\");\n const [transferExplorerUrl, setTransferExplorerUrl] = useState(\n null,\n );\n const swapStepRef = useRef(swapStep);\n const syncingIntentSourcesRef = useRef(false);\n const lastSwapIntentRefreshAtRef = useRef(0);\n const [destinationBalance, setDestinationBalance] = useState(\n null,\n );\n const [swapHistory, setSwapHistory] = useState(() =>\n readSwapHistoryFromStorage(historyStorageKey),\n );\n const { entries: onrampHistory, recordSession: recordOnrampSession } =\n useOnrampHistory({\n ownerAddress,\n active: swapStep === \"history\",\n });\n const [currentSwapId, setCurrentSwapId] = useState(null);\n const [historyNow, setHistoryNow] = useState(() => Date.now());\n const currentSwapIdRef = useRef(null);\n const currentSwapStartedAtRef = useRef(0);\n const historyStorageKeyRef = useRef(historyStorageKey);\n const skipNextHistoryPersistRef = useRef(false);\n const explorerUrlsRef = useRef<{\n sourceExplorerUrl: string | null;\n destinationExplorerUrl: string | null;\n }>({ sourceExplorerUrl: null, destinationExplorerUrl: null });\n const activeQuoteInputKeyRef = useRef(\"\");\n\n // Ref to store swap intent hook allow/deny callbacks\n const swapIntentRef = useRef<{\n intent?: SwapIntentData;\n allow: () => void;\n deny: () => void;\n refresh: () => Promise;\n runId?: number;\n quoteInputKey?: string;\n } | null>(null);\n\n const startIntentFetchTiming = useCallback(\n ({\n background,\n operation,\n quoteInputKey,\n runId,\n }: {\n background: boolean;\n operation: string;\n quoteInputKey: string;\n runId: number;\n }) => {\n const startTimeMs = Date.now();\n const timing: IntentFetchTiming = {\n background,\n operation,\n quoteInputKey,\n runId,\n startTimeMs,\n walletAddress: ownerAddress ?? null,\n };\n\n latestIntentFetchRunIdRef.current = runId;\n intentFetchTimingRef.current = timing;\n intentUiRenderLoggedRunIdRef.current = null;\n setIntentFetchTiming(timing);\n console.log(\"[NexusWidget] intent fetch start\", {\n runId,\n walletAddress: timing.walletAddress,\n operation,\n quoteInputKey,\n background,\n dateNow: startTimeMs,\n date: new Date(startTimeMs),\n });\n return timing;\n },\n [ownerAddress],\n );\n\n const finishIntentFetchTiming = useCallback(\n (runId: number, status: \"resolved\" | \"failed\" = \"resolved\") => {\n const timing = intentFetchTimingRef.current;\n if (!timing || timing.runId !== runId) return;\n if (timing.endTimeMs !== undefined) return;\n\n const endTimeMs = Date.now();\n if (latestIntentFetchRunIdRef.current !== runId) {\n return;\n }\n\n const fetchDurationMs = endTimeMs - timing.startTimeMs;\n const completedTiming: IntentFetchTiming = {\n ...timing,\n endTimeMs,\n fetchDurationMs,\n };\n intentFetchTimingRef.current = completedTiming;\n setIntentFetchTiming(completedTiming);\n console.log(\"[NexusWidget] intent fetch end\", {\n runId,\n walletAddress: timing.walletAddress,\n operation: timing.operation,\n quoteInputKey: timing.quoteInputKey,\n status,\n dateNow: endTimeMs,\n date: new Date(endTimeMs),\n });\n console.log(\"[NexusWidget] intent fetch total\", {\n runId,\n walletAddress: timing.walletAddress,\n operation: timing.operation,\n quoteInputKey: timing.quoteInputKey,\n totalTimeSeconds: fetchDurationMs / 1000,\n elapsedMs: fetchDurationMs,\n dateNow: endTimeMs,\n });\n },\n [],\n );\n\n useEffect(() => {\n swapStepRef.current = swapStep;\n }, [swapStep]);\n\n useEffect(() => {\n return () => {\n if (drawerCloseTimerRef.current) {\n clearTimeout(drawerCloseTimerRef.current);\n }\n if (terminalBalanceRefreshTimerRef.current) {\n clearTimeout(terminalBalanceRefreshTimerRef.current);\n }\n if (rootHeightTransitionTimerRef.current) {\n clearTimeout(rootHeightTransitionTimerRef.current);\n }\n };\n }, []);\n\n const isQuoteEditLocked = useCallback(\n () => swapStepRef.current === \"choose-swap-asset\",\n [],\n );\n\n const getQuoteRequestDelay = useCallback(() => {\n if (immediateQuoteAfterSourceEditRef.current) {\n immediateQuoteAfterSourceEditRef.current = false;\n return 0;\n }\n return EXACT_OUT_INPUT_DEBOUNCE_MS;\n }, []);\n\n const startRootHeightTransition = useCallback(() => {\n setShouldAnimateRootHeight(true);\n if (rootHeightTransitionTimerRef.current) {\n clearTimeout(rootHeightTransitionTimerRef.current);\n }\n rootHeightTransitionTimerRef.current = setTimeout(() => {\n setShouldAnimateRootHeight(false);\n rootHeightTransitionTimerRef.current = null;\n }, ROOT_HEIGHT_TRANSITION_MS);\n }, []);\n\n const closeDrawerToIdle = useCallback(() => {\n const isDrawerStep =\n swapStep === \"choose-swap-asset\" ||\n swapStep === \"choose-receive-asset\" ||\n swapStep === \"enter-recipient\";\n\n if (!isDrawerStep) {\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n return;\n }\n\n if (drawerCloseTimerRef.current) {\n clearTimeout(drawerCloseTimerRef.current);\n }\n\n setClosingDrawerStep(swapStep);\n drawerCloseTimerRef.current = setTimeout(() => {\n if (\n swapStep === \"choose-swap-asset\" ||\n swapStep === \"choose-receive-asset\"\n ) {\n startRootHeightTransition();\n }\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n setClosingDrawerStep(null);\n drawerCloseTimerRef.current = null;\n }, DRAWER_CLOSE_MS);\n }, [startRootHeightTransition, swapStep]);\n\n const openDrawerStep = useCallback(\n (nextStep: SwapStep) => {\n if (drawerCloseTimerRef.current) {\n clearTimeout(drawerCloseTimerRef.current);\n drawerCloseTimerRef.current = null;\n }\n if (\n nextStep === \"choose-swap-asset\" ||\n nextStep === \"choose-receive-asset\"\n ) {\n startRootHeightTransition();\n }\n setClosingDrawerStep(null);\n swapStepRef.current = nextStep;\n setSwapStep(nextStep);\n },\n [startRootHeightTransition],\n );\n\n const syncRootContentHeight = useCallback((animate = false) => {\n const element = rootContentRef.current;\n if (!element) return;\n\n const nextHeight = Math.ceil(\n Math.max(element.getBoundingClientRect().height, element.scrollHeight),\n );\n if (nextHeight <= 0) return;\n\n if (rootContentHeightRef.current === nextHeight) {\n setHasMeasuredRootContent(true);\n return;\n }\n\n rootContentHeightRef.current = nextHeight;\n setShouldAnimateRootHeight(animate);\n if (rootHeightTransitionTimerRef.current) {\n clearTimeout(rootHeightTransitionTimerRef.current);\n rootHeightTransitionTimerRef.current = null;\n }\n if (animate) {\n rootHeightTransitionTimerRef.current = setTimeout(() => {\n setShouldAnimateRootHeight(false);\n rootHeightTransitionTimerRef.current = null;\n }, ROOT_HEIGHT_TRANSITION_MS);\n }\n setRootContentHeight(nextHeight);\n setHasMeasuredRootContent(true);\n }, []);\n\n useLayoutEffect(() => {\n syncRootContentHeight(true);\n\n const element = rootContentRef.current;\n if (!element || typeof ResizeObserver === \"undefined\") return;\n\n let frame = 0;\n const observer = new ResizeObserver(() => {\n if (frame) {\n window.cancelAnimationFrame(frame);\n }\n frame = window.requestAnimationFrame(() => {\n syncRootContentHeight(false);\n });\n });\n\n observer.observe(element);\n\n return () => {\n if (frame) {\n window.cancelAnimationFrame(frame);\n }\n observer.disconnect();\n };\n }, [activeMode, swapStep, syncRootContentHeight]);\n\n useEffect(() => {\n currentSwapIdRef.current = currentSwapId;\n }, [currentSwapId]);\n\n useEffect(() => {\n if (historyStorageKeyRef.current === historyStorageKey) return;\n historyStorageKeyRef.current = historyStorageKey;\n skipNextHistoryPersistRef.current = true;\n setSwapHistory(readSwapHistoryFromStorage(historyStorageKey));\n }, [historyStorageKey]);\n\n useEffect(() => {\n if (skipNextHistoryPersistRef.current) {\n skipNextHistoryPersistRef.current = false;\n return;\n }\n\n writeSwapHistoryToStorage(historyStorageKey, swapHistory);\n }, [historyStorageKey, swapHistory]);\n\n useEffect(() => {\n if (swapStep !== \"history\") return;\n const timer = window.setInterval(() => setHistoryNow(Date.now()), 30000);\n return () => window.clearInterval(timer);\n }, [swapStep]);\n\n const normalizeAddress = (value?: string | null) =>\n (value ?? \"\").toLowerCase();\n\n const getTokenLookupAddress = (value?: string | null) => {\n if (!value) return \"\";\n return isNativeTokenAddress(value) ? zeroAddress : value.toLowerCase();\n };\n\n const findBalanceTokenLogo = (\n chainId?: number,\n contractAddress?: string,\n symbol?: string,\n ) => {\n if (!chainId) return \"\";\n const lookupAddress = getTokenLookupAddress(contractAddress);\n const lookupSymbol = symbol?.toUpperCase();\n let symbolMatchLogo = \"\";\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n if (breakdown.chain?.id !== chainId) continue;\n const breakdownAddress = getTokenLookupAddress(\n breakdown.contractAddress,\n );\n const addressMatches =\n lookupAddress && breakdownAddress === lookupAddress;\n const symbolMatches =\n lookupSymbol &&\n [breakdown.symbol, asset.symbol]\n .filter(Boolean)\n .some((candidate) => candidate.toUpperCase() === lookupSymbol);\n const logo =\n getLogoFromMetadata(breakdown) || getLogoFromMetadata(asset);\n\n if (addressMatches && logo) return logo;\n if (!symbolMatchLogo && symbolMatches && logo) {\n symbolMatchLogo = logo;\n }\n }\n }\n\n return symbolMatchLogo;\n };\n\n const findSupportedTokenLogo = (\n chains: any[] | null | undefined,\n chainId?: number,\n contractAddress?: string,\n symbol?: string,\n ) => {\n if (!chainId) return \"\";\n const chain = chains?.find(\n (item: any) => Number(item?.id ?? item?.chainId) === chainId,\n );\n const tokens = chain?.tokens ?? chain?.assets ?? [];\n const lookupAddress = getTokenLookupAddress(contractAddress);\n const lookupSymbol = symbol?.toUpperCase();\n\n const addressMatch =\n lookupAddress &&\n tokens.find((token: any) => {\n const tokenAddress = getTokenLookupAddress(\n token?.contractAddress ?? token?.address ?? token?.tokenAddress,\n );\n return tokenAddress === lookupAddress;\n });\n const symbolMatch =\n lookupSymbol &&\n tokens.find((token: any) => {\n const tokenSymbol = (token?.symbol ?? token?.tokenSymbol ?? \"\")\n .toString()\n .toUpperCase();\n return tokenSymbol === lookupSymbol;\n });\n\n return (\n getLogoFromMetadata(addressMatch) || getLogoFromMetadata(symbolMatch)\n );\n };\n\n const resolveTokenLogo = (\n token:\n | {\n address?: string;\n contractAddress?: string;\n logo?: string;\n symbol?: string;\n tokenAddress?: string;\n tokenSymbol?: string;\n }\n | undefined,\n chainId?: number,\n ) => {\n const explicitLogo = getLogoFromMetadata(token);\n if (explicitLogo) return explicitLogo;\n\n const contractAddress =\n token?.contractAddress ?? token?.address ?? token?.tokenAddress;\n const symbol = token?.symbol ?? token?.tokenSymbol;\n const citreaToken = findCitreaReceiveToken({\n address: contractAddress,\n chainId,\n symbol,\n });\n const tokenMeta = symbol\n ? TOKEN_METADATA[symbol as keyof typeof TOKEN_METADATA]\n : undefined;\n\n return (\n findBalanceTokenLogo(chainId, contractAddress, symbol) ||\n findSupportedTokenLogo(\n swapSupportedChainsAndTokens,\n chainId,\n contractAddress,\n symbol,\n ) ||\n findSupportedTokenLogo(\n supportedChainsAndTokens,\n chainId,\n contractAddress,\n symbol,\n ) ||\n citreaToken?.logo ||\n tokenMeta?.logo ||\n (contractAddress && isNativeTokenAddress(contractAddress)\n ? CHAIN_METADATA[chainId ?? 0]?.logo\n : \"\") ||\n \"\"\n );\n };\n\n const enrichIntentToken = <\n T extends {\n address?: string;\n contractAddress?: string;\n logo?: string;\n symbol?: string;\n tokenAddress?: string;\n tokenSymbol?: string;\n },\n >(\n token: T,\n chainId?: number,\n ): T => {\n const logo = resolveTokenLogo(token, chainId);\n return logo && logo !== token.logo ? { ...token, logo } : token;\n };\n\n const enrichTokenOptionLogo = (\n token?: SwapTokenOption,\n ): SwapTokenOption | undefined => {\n if (!token) return undefined;\n\n const chainMeta = token.chainId ? CHAIN_METADATA[token.chainId] : undefined;\n const logo = resolveTokenLogo(token, token.chainId);\n const next = {\n ...token,\n chainLogo: token.chainLogo || chainMeta?.logo,\n logo: token.logo || logo,\n };\n\n if (next.chainLogo === token.chainLogo && next.logo === token.logo) {\n return token;\n }\n\n return next;\n };\n\n const enrichSwapIntentTokenMetadata = (\n intent: SwapIntentData,\n ): SwapIntentData => ({\n ...intent,\n destination: {\n ...intent.destination,\n token: enrichIntentToken(\n intent.destination.token,\n intent.destination.chain.id,\n ),\n },\n sources: (intent.sources ?? []).map((source) => ({\n ...source,\n token: enrichIntentToken(source.token, source.chain.id),\n })),\n });\n\n const buildIntentSourceToken = (\n source: SwapIntentData[\"sources\"][number],\n ): SwapTokenOption => {\n let matchedAsset: any;\n let matchedBreakdown: any;\n const sourceAddress = normalizeAddress(source.token.contractAddress);\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n const addressMatches =\n normalizeAddress(breakdown.contractAddress) === sourceAddress;\n const symbolMatches =\n breakdown.symbol === source.token.symbol ||\n asset.symbol === source.token.symbol;\n if (\n breakdown.chain?.id === source.chain.id &&\n (addressMatches || symbolMatches)\n ) {\n matchedAsset = asset;\n matchedBreakdown = breakdown;\n break;\n }\n }\n if (matchedBreakdown) break;\n }\n\n const chainMeta = CHAIN_METADATA[source.chain.id];\n const sourceValue = Number((source as any).value ?? 0);\n const isNativeSource = isNativeTokenAddress(source.token.contractAddress);\n const nativeCurrency = chainMeta?.nativeCurrency;\n const sourceSymbol =\n isNativeSource && (!source.token.symbol || !matchedAsset?.logo)\n ? nativeCurrency?.symbol || source.token.symbol\n : source.token.symbol || nativeCurrency?.symbol || \"\";\n const sourceDecimals =\n isNativeSource && nativeCurrency?.decimals !== undefined\n ? nativeCurrency.decimals\n : source.token.decimals;\n const sourceLogo = resolveTokenLogo(source.token, source.chain.id);\n\n return {\n contractAddress: source.token.contractAddress,\n symbol: sourceSymbol,\n name: sourceSymbol,\n logo: sourceLogo ?? \"\",\n decimals: sourceDecimals,\n balance: matchedBreakdown?.balance\n ? `${matchedBreakdown.balance} ${sourceSymbol}`\n : `${source.amount} ${sourceSymbol}`,\n balanceInFiat:\n matchedBreakdown?.balanceInFiat != null\n ? `$${Number(matchedBreakdown.balanceInFiat).toFixed(2)}`\n : Number.isFinite(sourceValue)\n ? `$${sourceValue.toFixed(2)}`\n : \"$0.00\",\n chainId: source.chain.id,\n chainName: getShortChainName(\n source.chain.id,\n chainMeta?.name ?? source.chain.name,\n ),\n chainLogo: chainMeta?.logo ?? source.chain.logo,\n userAmount: source.amount,\n userAmountUsd: Number.isFinite(sourceValue) ? source.value : undefined,\n userAmountMode: \"token\",\n };\n };\n\n const clearPendingSwapIntent = (\n clearQuote = true,\n options: { keepQuoteRefreshing?: boolean } = {},\n ) => {\n swapRunIdRef.current += 1;\n swapIntentRef.current?.deny();\n swapIntentRef.current = null;\n setIntentLoading(false);\n setTxError(null);\n if (!options.keepQuoteRefreshing) {\n setQuoteRefreshing(false);\n }\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setSwapQuoteIssue(null);\n resetProgressEvents();\n if (swapStepsListRef.current.length > 0 || steps.length > 0) {\n swapStepsListRef.current = [];\n resetSteps();\n } else {\n swapStepsListRef.current = [];\n }\n if (clearQuote) {\n setIntentToAmount(undefined);\n setIntentFeeUsd(undefined);\n setIntentData(null);\n if (!options.keepQuoteRefreshing) {\n setPredictiveQuote(null);\n }\n }\n };\n\n const clearSelectedSources = () => {\n setFromTokens((current) => (current.length === 0 ? current : []));\n setSourceSelectionTouched(false);\n setDepositSourceFilter(\"all\");\n setExactOutQuoteSourceModeValue(\"all\");\n };\n\n const resetExactOutSourcesToAuto = () => {\n setFromTokens((current) => (current.length === 0 ? current : []));\n setSourceSelectionTouched(false);\n setDepositSourceFilter(\"all\");\n setExactOutQuoteSourceModeValue(\"all\");\n setSourceSelectionRevision((current) => current + 1);\n };\n\n const getSourceAmountInput = (tokens: SwapTokenOption[]) => {\n const total = tokens.reduce(\n (sum, token) => sum + Number(token.userAmount || 0),\n 0,\n );\n return total > 0 ? String(total) : \"\";\n };\n\n const minimumSourceUsd = new Decimal(1);\n const hasMinimumSourceUsdValue = (value: unknown) =>\n (parseFiatNumber(value) ?? new Decimal(0)).gte(minimumSourceUsd);\n const hasMinimumSourceUsdBalance = (\n token: Pick,\n ) => hasMinimumSourceUsdValue(token.balanceInFiat);\n const filterMinimumSourceUsdTokens = (tokens: SwapTokenOption[]) =>\n tokens.filter(hasMinimumSourceUsdBalance);\n\n const getTokenUsdRateCacheKeyFromParts = (\n chainId?: number,\n contractAddress?: string,\n symbol?: string,\n ) => {\n if (!chainId || !symbol) return \"\";\n return [\n chainId,\n (contractAddress || zeroAddress).toLowerCase(),\n symbol.toUpperCase(),\n ].join(\":\");\n };\n\n const getTokenUsdRateCacheKey = (\n token?: Pick,\n ) =>\n getTokenUsdRateCacheKeyFromParts(\n token?.chainId,\n token?.contractAddress,\n token?.symbol,\n );\n\n const getSymbolUsdRateCacheKey = (symbol?: string) =>\n symbol ? symbol.trim().toUpperCase() : \"\";\n\n const getCachedIntentUsdRate = (\n token?: Pick,\n ) => {\n const tokenKey = getTokenUsdRateCacheKey(token);\n const cached = tokenKey\n ? intentDestinationUsdRateCacheRef.current[tokenKey]\n : undefined;\n const rate = parseFiatNumber(cached?.rate);\n return rate && rate.gt(0) ? rate : undefined;\n };\n\n const cacheDestinationUsdRateFromIntent = (\n intent?: SwapIntentData | null,\n ) => {\n const destination = intent?.destination;\n const amount = parseFiatNumber(destination?.amount);\n const value = parseFiatNumber(destination?.value);\n const chainId = destination?.chain?.id;\n const symbol = destination?.token?.symbol;\n\n if (\n !amount ||\n !value ||\n amount.lte(0) ||\n value.lte(0) ||\n !chainId ||\n !symbol\n ) {\n return;\n }\n\n const rate = value.div(amount);\n if (!rate.isFinite() || rate.lte(0)) return;\n\n const cached: CachedIntentUsdRate = {\n amount: amount.toFixed(),\n rate: rate.toDecimalPlaces(18).toFixed(),\n updatedAt: Date.now(),\n value: value.toFixed(),\n };\n const tokenKey = getTokenUsdRateCacheKeyFromParts(\n chainId,\n destination?.token?.contractAddress,\n symbol,\n );\n if (tokenKey) {\n intentDestinationUsdRateCacheRef.current[tokenKey] = cached;\n }\n\n const symbolKey = getSymbolUsdRateCacheKey(symbol);\n if (symbolKey) {\n intentSymbolUsdRateCacheRef.current[symbolKey] = cached;\n }\n };\n\n const getSwapBalanceTotalUsd = () =>\n (swapBalance ?? []).reduce((sum, asset) => {\n const breakdown = asset.breakdown ?? [];\n if (breakdown.length > 0) {\n return sum.plus(\n breakdown.reduce((breakdownSum, item) => {\n const value = parseFiatNumber(item.balanceInFiat) ?? new Decimal(0);\n return value.gte(minimumSourceUsd)\n ? breakdownSum.plus(value)\n : breakdownSum;\n }, new Decimal(0)),\n );\n }\n\n const value = parseFiatNumber(asset.balanceInFiat) ?? new Decimal(0);\n return value.gte(minimumSourceUsd) ? sum.plus(value) : sum;\n }, new Decimal(0));\n\n const getTokenUsdRate = (token: SwapTokenOption) => {\n const tokenBalance = parseFiatNumber(token.balance) ?? new Decimal(0);\n const fiatBalance = parseFiatNumber(token.balanceInFiat) ?? new Decimal(0);\n if (tokenBalance.gt(0) && fiatBalance.gt(0)) {\n return fiatBalance.div(tokenBalance);\n }\n\n const priceUsd = parseFiatNumber(token.priceUSD);\n if (priceUsd && priceUsd.gt(0)) {\n return priceUsd;\n }\n\n const fallbackRate = getFiatValue(1, token.symbol);\n if (Number.isFinite(fallbackRate) && fallbackRate > 0) {\n return new Decimal(fallbackRate);\n }\n\n return getCachedIntentUsdRate(token) ?? new Decimal(0);\n };\n const getUsdRateForSymbol = (symbol?: string) => {\n if (!symbol) return new Decimal(0);\n const fiat = getFiatValue(1, symbol);\n if (Number.isFinite(fiat) && fiat > 0) {\n return new Decimal(fiat);\n }\n\n const cached =\n intentSymbolUsdRateCacheRef.current[getSymbolUsdRateCacheKey(symbol)];\n const rate = parseFiatNumber(cached?.rate);\n return rate && rate.gt(0) ? rate : new Decimal(0);\n };\n\n const getFeeTokenLookupAddress = (value?: string | null) => {\n const lower = (value ?? \"\").toLowerCase();\n if (!lower || lower === \"0x\" || isNativeTokenAddress(lower)) {\n return zeroAddress;\n }\n return lower;\n };\n\n const getTokenUsdRateFromBalances = (\n chainId?: number,\n contractAddress?: string,\n symbol?: string,\n ) => {\n if (!chainId) return undefined;\n const lookupAddress = getFeeTokenLookupAddress(contractAddress);\n const lookupSymbol = symbol?.toUpperCase();\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n if (breakdown.chain?.id !== chainId) continue;\n const breakdownAddress = getFeeTokenLookupAddress(\n breakdown.contractAddress,\n );\n const addressMatches =\n lookupAddress && breakdownAddress === lookupAddress;\n const symbolMatches =\n lookupSymbol &&\n [breakdown.symbol, asset.symbol]\n .filter(Boolean)\n .some((candidate) => candidate.toUpperCase() === lookupSymbol);\n if (!addressMatches && !symbolMatches) continue;\n\n const balance = parseFiatNumber(breakdown.balance);\n const fiatBalance = parseFiatNumber(breakdown.balanceInFiat);\n if (balance && fiatBalance && balance.gt(0) && fiatBalance.gt(0)) {\n return fiatBalance.div(balance);\n }\n }\n }\n\n return undefined;\n };\n\n const getTokenUsdRateFromSupportedChains = (\n chains: any[] | null | undefined,\n chainId?: number,\n contractAddress?: string,\n symbol?: string,\n ) => {\n if (!chainId) return undefined;\n const chain = chains?.find(\n (item: any) => Number(item?.id ?? item?.chainId) === chainId,\n );\n const tokens = chain?.tokens ?? chain?.assets ?? [];\n const lookupAddress = getFeeTokenLookupAddress(contractAddress);\n const lookupSymbol = symbol?.toUpperCase();\n const matchedToken = tokens.find((token: any) => {\n const tokenAddress = getFeeTokenLookupAddress(\n token?.contractAddress ?? token?.address ?? token?.tokenAddress,\n );\n const addressMatches = lookupAddress && tokenAddress === lookupAddress;\n const tokenSymbol = (token?.symbol ?? token?.tokenSymbol ?? \"\")\n .toString()\n .toUpperCase();\n const symbolMatches = lookupSymbol && tokenSymbol === lookupSymbol;\n return addressMatches || symbolMatches;\n });\n const priceUsd = parseFiatNumber(\n matchedToken?.priceUSD ??\n matchedToken?.priceUsd ??\n matchedToken?.usdPrice ??\n matchedToken?.price,\n );\n return priceUsd && priceUsd.gt(0) ? priceUsd : undefined;\n };\n\n const getIntentDestinationGasUsdValue = (intent?: SwapIntentData | null) => {\n const gas = intent?.destination?.gas;\n const explicitValue = parseFiatNumber(gas?.value);\n if (explicitValue && explicitValue.gt(0)) return explicitValue;\n\n const amount = parseFiatNumber(gas?.amount);\n if (!amount || amount.lte(0)) return undefined;\n\n const chainId = intent?.destination?.chain?.id;\n const contractAddress = gas?.token?.contractAddress;\n const symbol = gas?.token?.symbol;\n const rate =\n getTokenUsdRateFromBalances(chainId, contractAddress, symbol) ??\n getTokenUsdRateFromSupportedChains(\n swapSupportedChainsAndTokens,\n chainId,\n contractAddress,\n symbol,\n ) ??\n getTokenUsdRateFromSupportedChains(\n supportedChainsAndTokens,\n chainId,\n contractAddress,\n symbol,\n ) ??\n getUsdRateForSymbol(symbol);\n\n return rate.gt(0) ? amount.mul(rate) : undefined;\n };\n\n const getCachedDestinationUsdRate = (token?: SwapTokenOption) => {\n return getCachedIntentUsdRate(token);\n };\n\n const resolveUsdRateForSymbol = async (symbol?: string) => {\n if (!symbol) return new Decimal(0);\n\n const localRate = getUsdRateForSymbol(symbol);\n if (localRate.gt(0)) return localRate;\n\n try {\n const resolvedRate = await resolveTokenUsdRate(symbol);\n return resolvedRate && resolvedRate > 0\n ? new Decimal(resolvedRate)\n : new Decimal(0);\n } catch {\n return new Decimal(0);\n }\n };\n\n const getTokenUsdValue = (\n token: SwapTokenOption,\n fallbackAmount?: string,\n ) => {\n const amountNumber =\n parseFiatNumber(token.userAmount || fallbackAmount) ?? new Decimal(0);\n if (amountNumber.lte(0)) return new Decimal(0);\n const quotedUsd = parseFiatNumber(token.userAmountUsd);\n if (quotedUsd && quotedUsd.gte(0)) return quotedUsd;\n if (token.userAmountMode === \"usd\") return amountNumber;\n\n const rate = getTokenUsdRate(token);\n return rate.gt(0) ? amountNumber.mul(rate) : new Decimal(0);\n };\n\n const getTokenBalanceAmount = (token: SwapTokenOption) =>\n parseFiatNumber(token.balance) ?? new Decimal(0);\n\n const getTokenBalanceUsd = (token: SwapTokenOption) =>\n parseFiatNumber(token.balanceInFiat) ?? new Decimal(0);\n\n const getSdkExactOutSourcePriority = (token: SwapTokenOption) => {\n const isSameChain =\n Boolean(token.chainId && toToken?.chainId) &&\n token.chainId === toToken?.chainId;\n const isSameToken =\n Boolean(token.contractAddress && toToken?.contractAddress) &&\n ((isNativeTokenAddress(token.contractAddress) &&\n isNativeTokenAddress(toToken?.contractAddress)) ||\n token.contractAddress.toLowerCase() ===\n toToken?.contractAddress.toLowerCase());\n const isStable = isSdkExactOutStableSymbol(token.symbol);\n const isGas = isNativeTokenAddress(token.contractAddress);\n const isEthereum = token.chainId === ETHEREUM_MAINNET_CHAIN_ID;\n\n if (isSameChain) {\n if (isSameToken) return 1;\n if (isStable) return 2;\n if (isGas) return 3;\n return 4;\n }\n\n if (isEthereum) {\n if (isSameToken) return 8;\n if (isStable) return 9;\n if (isGas) return 10;\n return 11;\n }\n\n if (isSameToken) return 5;\n if (isStable) return 6;\n return 7;\n };\n\n const sortExactOutSourcesBySdkPriority = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const priorityDiff =\n getSdkExactOutSourcePriority(a) - getSdkExactOutSourcePriority(b);\n if (priorityDiff !== 0) return priorityDiff;\n\n const usdDiff = getTokenBalanceUsd(b).cmp(getTokenBalanceUsd(a));\n if (usdDiff !== 0) return usdDiff;\n\n return `${a.symbol} ${a.chainName ?? \"\"}`.localeCompare(\n `${b.symbol} ${b.chainName ?? \"\"}`,\n );\n });\n\n const getTokenAmountForUsd = (token: SwapTokenOption, usdAmount: Decimal) => {\n const rate = getTokenUsdRate(token);\n if (rate.lte(0) || usdAmount.lte(0)) return new Decimal(0);\n return usdAmount.div(rate);\n };\n\n const getUsdForTokenAmount = (\n token: SwapTokenOption,\n tokenAmount: Decimal,\n ) => {\n const rate = getTokenUsdRate(token);\n if (rate.lte(0) || tokenAmount.lte(0)) return new Decimal(0);\n return tokenAmount.mul(rate);\n };\n\n const getExactOutDestinationBalanceCoverage = ({\n requestedAmount,\n requestedUsd,\n producedAmount,\n producedUsd,\n token = toToken,\n }: {\n requestedAmount?: Decimal;\n requestedUsd?: Decimal;\n producedAmount?: Decimal;\n producedUsd?: Decimal;\n token?: SwapTokenOption;\n }) => {\n if (\n (activeMode !== \"deposit\" && activeMode !== \"send\") ||\n !token ||\n !requestedAmount ||\n requestedAmount.lte(0)\n ) {\n return null;\n }\n\n const balanceAmount =\n parseFiatNumber(destinationBalance) ??\n parseFiatNumber(token.balance) ??\n new Decimal(0);\n if (balanceAmount.lte(0)) return null;\n\n const externalAmount =\n producedAmount && producedAmount.gt(0) ? producedAmount : new Decimal(0);\n const uncoveredAmount = Decimal.max(\n requestedAmount.minus(externalAmount),\n new Decimal(0),\n );\n const coveredAmount = Decimal.min(balanceAmount, uncoveredAmount);\n if (coveredAmount.lte(0)) return null;\n\n const requestedRate =\n requestedUsd && requestedUsd.gt(0)\n ? requestedUsd.div(requestedAmount)\n : undefined;\n const producedRate =\n producedUsd && producedUsd.gt(0) && producedAmount && producedAmount.gt(0)\n ? producedUsd.div(producedAmount)\n : undefined;\n const fallbackRate = getTokenUsdRate(token);\n const usdRate =\n requestedRate && requestedRate.gt(0)\n ? requestedRate\n : producedRate && producedRate.gt(0)\n ? producedRate\n : fallbackRate.gt(0)\n ? fallbackRate\n : undefined;\n\n return {\n amount: coveredAmount,\n usd: usdRate ? coveredAmount.mul(usdRate) : undefined,\n };\n };\n\n const buildDestinationBalanceDisplayToken = (\n coverage: ReturnType,\n token?: SwapTokenOption,\n ): SwapTokenOption | null => {\n if (!coverage || !token || coverage.amount.lte(0)) return null;\n\n const amount = coverage.amount\n .toDecimalPlaces(Math.max(0, token.decimals ?? 18), Decimal.ROUND_DOWN)\n .toFixed();\n const usd = coverage.usd?.toDecimalPlaces(6, Decimal.ROUND_DOWN).toFixed();\n const balanceUsd = coverage.usd\n ? `$${coverage.usd.toDecimalPlaces(2, Decimal.ROUND_DOWN).toFixed()}`\n : token.balanceInFiat || \"$0.00\";\n\n return {\n ...token,\n balance: amount,\n balanceInFiat: balanceUsd,\n userAmount: amount,\n userAmountMode: \"token\",\n userAmountUsd: usd,\n };\n };\n\n const cacheSymbolUsdRate = (symbol: string | undefined, rate: Decimal) => {\n const symbolKey = getSymbolUsdRateCacheKey(symbol);\n if (!symbolKey || rate.lte(0)) return;\n\n intentSymbolUsdRateCacheRef.current[symbolKey] = {\n amount: \"1\",\n rate: rate.toDecimalPlaces(18).toFixed(),\n updatedAt: Date.now(),\n value: rate.toFixed(),\n };\n };\n\n const getPredictiveDestinationKey = (token?: SwapTokenOption) => {\n const tokenKey = getTokenUsdRateCacheKey(token);\n return tokenKey ? `destination:${tokenKey}` : \"\";\n };\n\n const getPredictiveSourceKey = (token: SwapTokenOption) =>\n [\n token.chainId ?? \"unknown\",\n (token.contractAddress || zeroAddress).toLowerCase(),\n token.symbol.toUpperCase(),\n ].join(\":\");\n\n const getPredictiveQuoteCacheKey = (\n mode = activeMode,\n type = swapType,\n destination = toToken,\n sources = fromTokens,\n ) => {\n const destinationKey = getPredictiveDestinationKey(destination);\n if (!destinationKey) return \"\";\n if (mode !== \"swap\" || type !== \"exactIn\") {\n return `exactOut:${destinationKey}`;\n }\n\n const sourceKey = getExpandedSourceTokens(sources)\n .map(getPredictiveSourceKey)\n .sort()\n .join(\"+\");\n return sourceKey ? `exactIn:${sourceKey}->${destinationKey}` : \"\";\n };\n\n const getPredictiveDisplayAmount = (\n amount: Decimal,\n token?: Pick,\n ) => {\n const decimals = Math.min(\n PREDICTIVE_QUOTE_DISPLAY_DECIMALS,\n Math.max(0, token?.decimals ?? 18),\n );\n return amount.toDecimalPlaces(decimals, Decimal.ROUND_DOWN).toFixed();\n };\n\n const resolveUsdRateForToken = async (token?: SwapTokenOption) => {\n if (!token?.symbol) return new Decimal(0);\n\n const localRate = getTokenUsdRate(token);\n if (localRate.gt(0)) return localRate;\n\n const resolvedRate = await resolveUsdRateForSymbol(token.symbol);\n if (resolvedRate.gt(0)) {\n cacheSymbolUsdRate(token.symbol, resolvedRate);\n }\n return resolvedRate;\n };\n\n const getDestinationReceiveLimitUsd = (token?: SwapTokenOption) => {\n if (!token?.chainId) return undefined;\n const limit = DESTINATION_RECEIVE_LIMIT_USD_BY_CHAIN_ID[token.chainId];\n return limit ? new Decimal(limit) : undefined;\n };\n\n const getImmediateDestinationReceiveUsdRate = (token?: SwapTokenOption) => {\n const priceUsd = parseFiatNumber(token?.priceUSD);\n if (priceUsd && priceUsd.gt(0)) return priceUsd;\n\n const cachedRate = getCachedDestinationUsdRate(token);\n if (cachedRate && cachedRate.gt(0)) return cachedRate;\n\n if (!token) return undefined;\n const localRate = getTokenUsdRate(token);\n return localRate.gt(0) ? localRate : undefined;\n };\n\n const getExactInSourceUsdForReceiveLimit = (\n sourceTokens: SwapTokenOption[],\n inputAmount: string,\n ) => {\n if (sourceTokens.length === 0) return undefined;\n let hasPositiveSourceAmount = false;\n let totalUsd = new Decimal(0);\n\n for (const token of sourceTokens) {\n const fallbackAmount =\n sourceTokens.length === 1 ? inputAmount : undefined;\n const sourceAmount = parseFiatNumber(token.userAmount || fallbackAmount);\n if (!sourceAmount || sourceAmount.lte(0)) continue;\n\n hasPositiveSourceAmount = true;\n const sourceUsd = getTokenUsdValue(token, fallbackAmount);\n if (sourceUsd.lte(0)) return undefined;\n totalUsd = totalUsd.plus(sourceUsd);\n }\n\n return hasPositiveSourceAmount ? totalUsd : undefined;\n };\n\n const buildReceiveAmountIssue = ({\n destinationRate,\n destinationToken = toToken,\n inputAmount = amount,\n mode = activeMode,\n sourceTokens = fromTokens,\n type = swapType,\n }: {\n destinationRate?: Decimal;\n destinationToken?: SwapTokenOption;\n inputAmount?: string;\n mode?: NexusWidgetMode;\n sourceTokens?: SwapTokenOption[];\n type?: SwapType;\n } = {}): ReceiveAmountIssue | null => {\n const limit = getDestinationReceiveLimitUsd(destinationToken);\n if (!limit || !destinationToken) return null;\n\n const parsedAmount = parseFiatNumber(inputAmount);\n if (!parsedAmount || parsedAmount.lte(0)) return null;\n if (mode === \"swap\" && type === \"exactIn\" && sourceTokens.length === 0) {\n return null;\n }\n\n const chainName = getShortChainName(\n destinationToken.chainId,\n destinationToken.chainName,\n );\n const resolvedDestinationRate =\n destinationRate ??\n getImmediateDestinationReceiveUsdRate(destinationToken);\n\n if (!resolvedDestinationRate || resolvedDestinationRate.lte(0)) {\n return {\n ctaLabel: \"Price unavailable\",\n message: `Unable to price ${destinationToken.symbol} on ${chainName}. Select another receive token.`,\n type: \"unpricedReceiveToken\",\n };\n }\n\n let receiveUsd: Decimal | undefined;\n if (mode === \"swap\" && type === \"exactIn\") {\n receiveUsd = getExactInSourceUsdForReceiveLimit(\n sourceTokens,\n inputAmount,\n );\n if (!receiveUsd || receiveUsd.lte(0)) {\n return {\n ctaLabel: \"Price unavailable\",\n message: `Unable to price selected assets for ${chainName}'s receive limit.`,\n type: \"unpricedReceiveToken\",\n };\n }\n } else if (mode === \"deposit\" && depositAmountMode === \"usd\") {\n receiveUsd = parsedAmount;\n } else {\n receiveUsd = parsedAmount.mul(resolvedDestinationRate);\n }\n\n if (receiveUsd.gt(limit)) {\n return {\n ctaLabel: \"Receive limit exceeded\",\n message: `Maximum receive amount on ${chainName} is ${formatUsdDisplay(limit)}.`,\n type: \"receiveLimitExceeded\",\n };\n }\n\n return null;\n };\n\n const buildConfiguredAmountIssue = (\n inputAmount = amount,\n ): ReceiveAmountIssue | null => {\n if (!amountInputConfig || !inputAmount) return null;\n const parsedAmount = parseFiatNumber(inputAmount);\n if (!parsedAmount || parsedAmount.lte(0)) return null;\n const tokenSuffix = toToken?.symbol?.trim()\n ? ` ${toToken.symbol.trim()}`\n : \"\";\n\n const minAmount = parseFiatNumber(amountInputConfig.min);\n if (minAmount && parsedAmount.lt(minAmount)) {\n return {\n ctaLabel: \"Below minimum\",\n message: `Minimum deposit amount is ${minAmount.toFixed()}${tokenSuffix}.`,\n type: \"configuredAmountLimit\",\n };\n }\n\n const maxAmount = parseFiatNumber(amountInputConfig.max);\n if (maxAmount && parsedAmount.gt(maxAmount)) {\n return {\n ctaLabel: \"Above maximum\",\n message: `Maximum deposit amount is ${maxAmount.toFixed()}${tokenSuffix}.`,\n type: \"configuredAmountLimit\",\n };\n }\n\n return null;\n };\n\n const clearPreviewForBlockingAmountIssue = () => {\n clearPendingSwapIntent(true);\n setQuoteRefreshing(false);\n setIntentLoading(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setTxError(null);\n setSwapQuoteIssue(null);\n };\n\n const applyReceiveAmountIssue = (issue: ReceiveAmountIssue | null) => {\n const key = issue ? `${issue.type}:${issue.message}` : \"\";\n receiveAmountIssueRef.current = issue;\n if (receiveAmountIssueKeyRef.current !== key) {\n receiveAmountIssueKeyRef.current = key;\n setReceiveAmountIssue(issue);\n }\n if (!issue) return;\n\n clearPendingSwapIntent(true);\n setQuoteRefreshing(false);\n setIntentLoading(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setTxError(null);\n };\n\n const getPredictiveExactInSourceTokens = () => {\n const allocatedSources = getExactInSourceTokens(\n fromTokens,\n hasPositiveDecimalInput(amount) ? amount : undefined,\n );\n if (allocatedSources.length === 0) return [];\n\n return allocatedSources\n .map((token) => {\n const userAmount =\n token.userAmount ||\n (allocatedSources.length === 1 && hasPositiveDecimalInput(amount)\n ? amount\n : \"\");\n return { ...token, userAmount };\n })\n .filter((token) => hasPositiveDecimalInput(token.userAmount));\n };\n\n const sortUnifiedSourceTokens = (tokens: SwapTokenOption[]) =>\n [...tokens].sort((a, b) => {\n const fiatDiff = getTokenBalanceUsd(b).cmp(getTokenBalanceUsd(a));\n if (fiatDiff !== 0) return fiatDiff;\n return getTokenBalanceAmount(b).cmp(getTokenBalanceAmount(a));\n });\n\n const allocateUnifiedExactInToken = (\n token: SwapTokenOption,\n fallbackAmount?: string,\n ) => {\n if (!token.isUnified || !token.sourceTokens?.length) return [token];\n\n const rawAmount =\n parseFiatNumber(token.userAmount || fallbackAmount) ?? new Decimal(0);\n if (rawAmount.lte(0)) return [];\n\n const sortedSources = sortUnifiedSourceTokens(token.sourceTokens).filter(\n (source) =>\n source.chainId &&\n source.contractAddress &&\n getTokenBalanceAmount(source).gt(0) &&\n hasMinimumSourceUsdBalance(source),\n );\n const allocated: SwapTokenOption[] = [];\n\n if (token.userAmountMode === \"usd\") {\n let remainingUsd = rawAmount;\n\n for (const source of sortedSources) {\n if (remainingUsd.lte(0)) break;\n\n const availableUsd = getTokenBalanceUsd(source);\n if (availableUsd.lte(0)) continue;\n\n const targetUsd = Decimal.min(remainingUsd, availableUsd);\n const tokenAmount = getTokenAmountForUsd(\n source,\n targetUsd,\n ).toDecimalPlaces(\n Math.max(0, source.decimals || 18),\n Decimal.ROUND_DOWN,\n );\n if (tokenAmount.lte(0)) continue;\n\n const actualUsd = getUsdForTokenAmount(source, tokenAmount);\n allocated.push({\n ...source,\n userAmount: tokenAmount.toFixed(),\n userAmountMode: \"token\",\n userAmountUsd: actualUsd\n .toDecimalPlaces(6, Decimal.ROUND_DOWN)\n .toFixed(),\n });\n remainingUsd = remainingUsd.minus(targetUsd);\n }\n\n return allocated;\n }\n\n let remainingTokenAmount = rawAmount;\n\n for (const source of sortedSources) {\n if (remainingTokenAmount.lte(0)) break;\n\n const availableTokenAmount = getTokenBalanceAmount(source);\n if (availableTokenAmount.lte(0)) continue;\n\n const tokenAmount = Decimal.min(\n remainingTokenAmount,\n availableTokenAmount,\n ).toDecimalPlaces(Math.max(0, source.decimals || 18), Decimal.ROUND_DOWN);\n if (tokenAmount.lte(0)) continue;\n\n const actualUsd = getUsdForTokenAmount(source, tokenAmount);\n allocated.push({\n ...source,\n userAmount: tokenAmount.toFixed(),\n userAmountMode: \"token\",\n userAmountUsd: actualUsd\n .toDecimalPlaces(6, Decimal.ROUND_DOWN)\n .toFixed(),\n });\n remainingTokenAmount = remainingTokenAmount.minus(tokenAmount);\n }\n\n return allocated;\n };\n\n const getExactInSourceTokens = (\n tokens: SwapTokenOption[],\n fallbackAmount?: string,\n ) =>\n tokens\n .flatMap((token) =>\n token.isUnified\n ? allocateUnifiedExactInToken(token, fallbackAmount)\n : [token],\n )\n .filter(hasMinimumSourceUsdBalance);\n\n const hasPositiveDecimalInput = (value: unknown) =>\n Boolean(parseFiatNumber(value)?.gt(0));\n\n const hasPositiveSourceSpend = (token: SwapTokenOption) =>\n hasPositiveDecimalInput(token.userAmount) ||\n hasPositiveDecimalInput(token.userAmountUsd);\n\n const getReadyExactInSourceTokens = (tokens: SwapTokenOption[]) =>\n getExactInSourceTokens(tokens).filter(\n (token) =>\n Boolean(token.chainId && token.contractAddress) &&\n hasPositiveDecimalInput(token.userAmount),\n );\n\n const hasReadyExactInSwapInput = (\n tokens: SwapTokenOption[],\n destination?: SwapTokenOption,\n ) =>\n Boolean(\n destination?.chainId &&\n destination.contractAddress &&\n getReadyExactInSourceTokens(tokens).length > 0,\n );\n\n const getExpandedSourceTokens = (tokens: SwapTokenOption[]) => {\n const expanded = tokens.flatMap((token) =>\n token.isUnified && token.sourceTokens?.length\n ? token.sourceTokens\n : [token],\n );\n const seen = new Set();\n return expanded.filter((token) => {\n if (!token.chainId || !token.contractAddress) return false;\n if (\n !isSwapSupportedBySdkChainList(\n token.chainId,\n swapSupportedChainsAndTokens,\n )\n ) {\n return false;\n }\n const key = `${token.chainId}-${token.contractAddress.toLowerCase()}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n };\n\n const getNativeGasBalanceForChain = (chainId: number) => {\n const nativeSymbol =\n CHAIN_METADATA[chainId]?.nativeCurrency?.symbol?.toUpperCase();\n let balance = new Decimal(0);\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n if (breakdown.chain?.id !== chainId) continue;\n const breakdownSymbol = (\n breakdown.symbol ??\n asset.symbol ??\n \"\"\n ).toUpperCase();\n const assetSymbol = (asset.symbol ?? \"\").toUpperCase();\n const isNativeBalance =\n isNativeTokenAddress(breakdown.contractAddress) ||\n Boolean(\n nativeSymbol &&\n (breakdownSymbol === nativeSymbol || assetSymbol === nativeSymbol),\n );\n\n if (!isNativeBalance) continue;\n balance = balance.plus(\n parseFiatNumber(breakdown.balance) ?? new Decimal(0),\n );\n }\n }\n\n return balance;\n };\n\n const hasGasForSource = (token: SwapTokenOption) => {\n if (!token.chainId || !token.contractAddress) return false;\n const tokenBalance = parseFiatNumber(token.balance) ?? new Decimal(0);\n if (tokenBalance.lte(0)) return false;\n if (isNativeTokenAddress(token.contractAddress)) return true;\n return getNativeGasBalanceForChain(token.chainId).gt(0);\n };\n\n const getGasCapableBalanceSourceTokens = () => {\n const tokens: SwapTokenOption[] = [];\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n const chainId = breakdown.chain?.id;\n const contractAddress = breakdown.contractAddress;\n const balance = parseFiatNumber(breakdown.balance) ?? new Decimal(0);\n const fiatBalance = parseFiatNumber(breakdown.balanceInFiat);\n if (\n !chainId ||\n !contractAddress ||\n balance.lte(0) ||\n !fiatBalance ||\n fiatBalance.lt(minimumSourceUsd)\n )\n continue;\n\n const chainMeta = CHAIN_METADATA[chainId];\n const symbol = breakdown.symbol ?? asset.symbol;\n tokens.push({\n chainId,\n chainLogo: chainMeta?.logo ?? breakdown.chain?.logo,\n chainName: getShortChainName(\n chainId,\n chainMeta?.name ?? breakdown.chain?.name,\n ),\n contractAddress,\n decimals: breakdown.decimals ?? asset.decimals ?? 18,\n logo: asset.logo ?? \"\",\n name: symbol,\n symbol,\n balance: breakdown.balance,\n balanceInFiat:\n fiatBalance !== undefined\n ? `$${fiatBalance.toDecimalPlaces(2).toFixed()}`\n : \"$0.00\",\n });\n }\n }\n\n return getExpandedSourceTokens(tokens).filter(hasGasForSource);\n };\n\n const getMinimumBalanceSourceTokens = () =>\n filterMinimumSourceUsdTokens(\n getExpandedSourceTokens(\n swapBalance\n ? deriveTokenOptions(swapBalance, swapSupportedChainsAndTokens)\n : [],\n ),\n );\n const getHeldDestinationTokenOption = () => {\n if (!toToken?.chainId || !toToken.contractAddress) return undefined;\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n const chainId = breakdown.chain?.id;\n if (chainId !== toToken.chainId) continue;\n\n const breakdownAddress = breakdown.contractAddress;\n const addressMatches =\n breakdownAddress &&\n (breakdownAddress.toLowerCase() ===\n toToken.contractAddress.toLowerCase() ||\n (isNativeTokenAddress(breakdownAddress) &&\n isNativeTokenAddress(toToken.contractAddress)));\n const symbolMatches =\n (breakdown.symbol ?? asset.symbol ?? \"\").toUpperCase() ===\n toToken.symbol.toUpperCase();\n\n if (!addressMatches && !symbolMatches) continue;\n\n const balanceAmount = parseFiatNumber(breakdown.balance);\n if (!balanceAmount || balanceAmount.lte(0)) continue;\n\n const chainMeta = CHAIN_METADATA[chainId];\n const symbol = breakdown.symbol ?? asset.symbol ?? toToken.symbol;\n const fiatBalance = parseFiatNumber(breakdown.balanceInFiat);\n\n return {\n chainId,\n chainLogo:\n chainMeta?.logo ?? breakdown.chain?.logo ?? toToken.chainLogo,\n chainName: getShortChainName(\n chainId,\n chainMeta?.name ?? breakdown.chain?.name ?? toToken.chainName,\n ),\n contractAddress: breakdown.contractAddress ?? toToken.contractAddress,\n decimals:\n breakdown.decimals ?? asset.decimals ?? toToken.decimals ?? 18,\n logo: asset.logo ?? toToken.logo,\n name: symbol,\n symbol,\n balance: breakdown.balance,\n balanceInFiat:\n fiatBalance !== undefined\n ? `$${fiatBalance.toDecimalPlaces(2).toFixed()}`\n : \"$0.00\",\n } satisfies SwapTokenOption;\n }\n }\n\n return undefined;\n };\n\n const getDepositDestinationForSourceSelection = () => {\n const destination =\n activeMode === \"deposit\" ? selectedOpportunity : toToken;\n const chainId = destination?.chainId;\n const tokenAddress =\n activeMode === \"deposit\"\n ? selectedOpportunity?.tokenAddress\n : toToken?.contractAddress;\n const tokenSymbol =\n activeMode === \"deposit\"\n ? selectedOpportunity?.tokenSymbol\n : toToken?.symbol;\n\n if (!chainId || !tokenAddress || !tokenSymbol) return undefined;\n\n return {\n chainId,\n tokenAddress: tokenAddress as `0x${string}`,\n tokenSymbol,\n };\n };\n const getDestinationSourceIdForDeposit = () => {\n const destination = getDepositDestinationForSourceSelection();\n return destination\n ? getDepositSourceId(destination.tokenAddress, destination.chainId)\n : undefined;\n };\n const getDepositSourceTargetUsd = () => {\n if (activeMode !== \"deposit\") return undefined;\n const requestedUsd = depositUsdDecimal;\n if (!requestedUsd || requestedUsd.lte(0)) return undefined;\n\n const coverage = getExactOutDestinationBalanceCoverage({\n requestedAmount: depositTokenAmountForQuote,\n requestedUsd,\n token: toToken,\n });\n return Decimal.max(\n requestedUsd.minus(coverage?.usd ?? new Decimal(0)),\n new Decimal(0),\n );\n };\n\n const getDepositSourceIdsFromTokens = (tokens: SwapTokenOption[]) =>\n getExpandedSourceTokens(tokens)\n .filter((token) => token.chainId && token.contractAddress)\n .map((token) =>\n getDepositSourceId(token.contractAddress, token.chainId!),\n );\n\n const getDepositTokenOptionsBySourceId = () => {\n const map = new Map();\n const sourceTokens = [\n ...(swapBalance\n ? deriveTokenOptions(swapBalance, swapSupportedChainsAndTokens)\n : []),\n ...fromTokens,\n ];\n\n for (const token of getExpandedSourceTokens(sourceTokens)) {\n if (!token.chainId || !token.contractAddress) continue;\n const id = getDepositSourceId(token.contractAddress, token.chainId);\n if (!map.has(id)) {\n map.set(id, {\n ...token,\n userAmount: \"\",\n });\n }\n }\n\n return map;\n };\n\n const getDepositSourceTokensForIds = (sourceIds: string[]) => {\n const tokenBySourceId = getDepositTokenOptionsBySourceId();\n return sourceIds\n .map((sourceId) => tokenBySourceId.get(sourceId))\n .filter((token): token is SwapTokenOption => Boolean(token))\n .map((token) => ({ ...token, userAmount: \"\" }));\n };\n\n const getResolvedDepositSourceSelection = (options?: {\n filter?: DepositSourceFilter;\n selectedTokens?: SwapTokenOption[];\n isManualSelection?: boolean;\n targetAmountUsd?: Decimal;\n }) => {\n const destination = getDepositDestinationForSourceSelection();\n if (!destination) {\n return { sourcePoolIds: [], selectedSourceIds: [], fromSources: [] };\n }\n\n const manualSelection =\n options?.isManualSelection ?? sourceSelectionTouched;\n const selectedTokensForResolution = options?.selectedTokens ?? fromTokens;\n const selectedSourceIds = getDepositSourceIdsFromTokens(\n selectedTokensForResolution,\n );\n const destinationSourceId = getDestinationSourceIdForDeposit();\n const targetAmountUsd =\n options?.targetAmountUsd ??\n (activeMode === \"deposit\"\n ? getDepositSourceTargetUsd()\n : activeMode === \"send\"\n ? new Decimal(sendAmountUsd || 0)\n : undefined);\n\n return resolveDepositSourceSelection({\n swapBalance,\n destination,\n filter: manualSelection\n ? \"custom\"\n : (options?.filter ?? depositSourceFilter),\n selectedSourceIds,\n isManualSelection: manualSelection,\n minimumBalanceUsd: minimumSourceUsd.toNumber(),\n targetAmountUsd: targetAmountUsd?.toNumber(),\n excludedSourceIds: destinationSourceId ? [destinationSourceId] : [],\n });\n };\n\n const getExactOutSourceTokens = (\n mode: \"all\" | \"selected\" = exactOutQuoteSourceModeRef.current,\n targetAmountUsd?: Decimal,\n ) => {\n if (activeMode === \"deposit\") {\n const selection = getResolvedDepositSourceSelection({ targetAmountUsd });\n return getDepositSourceTokensForIds(\n mode === \"all\" ? selection.sourcePoolIds : selection.selectedSourceIds,\n );\n }\n\n if (activeMode === \"send\" && mode === \"selected\" && fromTokens.length > 0) {\n return filterMinimumSourceUsdTokens(\n getExpandedSourceTokens(fromTokens),\n ).filter(hasGasForSource);\n }\n\n return getGasCapableBalanceSourceTokens();\n };\n\n const buildExplicitSourcesPayload = (tokens: SwapTokenOption[]) => {\n const eligibleTokens = filterMinimumSourceUsdTokens(tokens).filter(\n (token) => token.chainId && token.contractAddress,\n );\n return {\n sources: eligibleTokens.map((token) => ({\n chainId: token.chainId!,\n tokenAddress: token.contractAddress as `0x${string}`,\n })),\n };\n };\n\n const getSdkSourceKey = (source: {\n chainId: number;\n tokenAddress: `0x${string}`;\n }) => {\n const normalizedAddress = isNativeTokenAddress(source.tokenAddress)\n ? zeroAddress\n : source.tokenAddress.toLowerCase();\n return `${source.chainId}:${normalizedAddress}`;\n };\n\n const dedupeSdkSources = (\n sources: Array<\n | {\n chainId: number;\n tokenAddress: `0x${string}`;\n }\n | undefined\n >,\n ) => {\n const seen = new Set();\n return sources.filter(\n (\n source,\n ): source is {\n chainId: number;\n tokenAddress: `0x${string}`;\n } => {\n if (!source) return false;\n const key = getSdkSourceKey(source);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n },\n );\n };\n\n const getHeldDestinationTokenSource = () => {\n const heldDestinationToken = getHeldDestinationTokenOption();\n if (\n !heldDestinationToken?.chainId ||\n !heldDestinationToken.contractAddress\n ) {\n return undefined;\n }\n\n return {\n chainId: heldDestinationToken.chainId,\n tokenAddress: heldDestinationToken.contractAddress as `0x${string}`,\n };\n };\n\n const shouldSendExactOutSourceAllowlist = () => {\n if (activeMode === \"deposit\") {\n return sourceSelectionTouched || depositSourceFilter !== \"all\";\n }\n\n if (activeMode === \"send\") {\n return exactOutQuoteSourceModeRef.current === \"selected\";\n }\n\n return true;\n };\n\n const buildExactOutSourcesPayload = (tokens: SwapTokenOption[]) => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") {\n return buildExplicitSourcesPayload(tokens);\n }\n\n const sourceTokens = shouldSendExactOutSourceAllowlist()\n ? tokens\n : getExactOutSourceTokens(\"all\");\n const explicitSources = buildExplicitSourcesPayload(sourceTokens).sources;\n const sources = dedupeSdkSources([\n ...explicitSources,\n getHeldDestinationTokenSource(),\n ]);\n\n return sources.length > 0 ? { sources } : {};\n };\n\n const buildPredictiveExactOutSources = async (requiredSourceUsd: Decimal) => {\n if (requiredSourceUsd.lte(0)) return [];\n\n const destinationKey = getTokenSelectionKey(toToken);\n const candidates = sortExactOutSourcesBySdkPriority(\n getExactOutSourceTokens(\n exactOutQuoteSourceModeRef.current,\n requiredSourceUsd,\n )\n .filter((token) => getTokenSelectionKey(token) !== destinationKey)\n .filter(hasMinimumSourceUsdBalance),\n );\n const sources: SwapTokenOption[] = [];\n let remainingUsd = requiredSourceUsd;\n\n for (const token of candidates) {\n if (remainingUsd.lte(0)) break;\n\n const availableUsd = getTokenBalanceUsd(token);\n if (availableUsd.lt(minimumSourceUsd)) continue;\n\n const rate = await resolveUsdRateForToken(token);\n if (rate.lte(0)) continue;\n\n const targetUsd = Decimal.min(remainingUsd, availableUsd);\n const tokenAmount = targetUsd\n .div(rate)\n .toDecimalPlaces(Math.max(0, token.decimals || 18), Decimal.ROUND_DOWN);\n if (tokenAmount.lte(0)) continue;\n\n sources.push({\n ...token,\n userAmount: tokenAmount.toFixed(),\n userAmountMode: \"token\",\n userAmountUsd: targetUsd\n .toDecimalPlaces(6, Decimal.ROUND_DOWN)\n .toFixed(),\n });\n remainingUsd = remainingUsd.minus(targetUsd);\n }\n\n return remainingUsd.gt(0.01) ? [] : sources;\n };\n\n const getErrorText = (error: unknown) => {\n const err = error as any;\n const parts = [\n err?.message,\n typeof error === \"string\" ? error : undefined,\n err?.code,\n ];\n\n try {\n if (err?.data) parts.push(JSON.stringify(err.data));\n } catch {\n // Ignore non-serializable SDK error metadata.\n }\n\n return parts.filter(Boolean).join(\" \");\n };\n\n const isInsufficientSourcesError = (error: unknown) => {\n const err = error as any;\n const message = getErrorText(error).toLowerCase();\n\n return (\n err?.code === ERROR_CODES.INSUFFICIENT_BALANCE ||\n message.includes(\"insufficient balance\") ||\n message.includes(\"sources are not enough\") ||\n (message.includes(\"source\") && message.includes(\"not enough\"))\n );\n };\n\n const isViemInvalidDecimalError = (error: unknown) =>\n getErrorText(error).toLowerCase().includes(\"not a valid decimal number\");\n\n const parseLabeledErrorDecimal = (text: string, label: string) => {\n const match = text.match(\n new RegExp(`${label}\\\\s*:\\\\s*\\\\$?\\\\s*([0-9][0-9,]*(?:\\\\.[0-9]+)?)`, \"i\"),\n );\n return match ? parseFiatNumber(match[1]) : undefined;\n };\n\n const getExactOutRequestedUsd = () => {\n const amountNumber = parseFiatNumber(amount);\n if (!amountNumber || amountNumber.lte(0) || !toToken?.symbol) {\n return undefined;\n }\n\n if (activeMode === \"deposit\" && depositAmountMode === \"usd\") {\n return amountNumber;\n }\n\n const fiatValue = getFiatValue(amountNumber.toNumber(), toToken.symbol);\n return Number.isFinite(fiatValue) && fiatValue > 0\n ? new Decimal(fiatValue)\n : undefined;\n };\n\n const getExactOutAvailableSourceUsd = (\n sourceTokensOverride?: SwapTokenOption[],\n ): Decimal => {\n const sumTokensWithDestinationCredit = (\n tokens: SwapTokenOption[],\n ): Decimal => {\n const heldDestinationToken = getHeldDestinationTokenOption();\n const heldDestinationKey = getTokenSelectionKey(heldDestinationToken);\n let hasHeldDestinationToken = false;\n\n const sourceTotal = tokens.reduce((sum, token) => {\n const value = parseFiatNumber(token.balanceInFiat) ?? new Decimal(0);\n const isHeldDestinationToken =\n heldDestinationKey &&\n getTokenSelectionKey(token) === heldDestinationKey;\n if (isHeldDestinationToken) {\n hasHeldDestinationToken = true;\n }\n\n return value.gt(0) &&\n (isHeldDestinationToken || value.gte(minimumSourceUsd))\n ? sum.plus(value)\n : sum;\n }, new Decimal(0));\n\n if (!heldDestinationToken || hasHeldDestinationToken) {\n return sourceTotal;\n }\n\n const heldDestinationUsd =\n parseFiatNumber(heldDestinationToken.balanceInFiat) ?? new Decimal(0);\n return heldDestinationUsd.gt(0)\n ? sourceTotal.plus(heldDestinationUsd)\n : sourceTotal;\n };\n\n if (\n sourceTokensOverride ||\n exactOutQuoteSourceModeRef.current === \"selected\"\n ) {\n const selectedSourceTokens = sourceTokensOverride ?? fromTokens;\n return sumTokensWithDestinationCredit(selectedSourceTokens);\n }\n\n return getExactOutTotalSourceBalanceUsd();\n };\n const getExactOutTotalSourceBalanceUsd = (): Decimal => {\n const allSourceTotal: Decimal = getExactOutAvailableSourceUsd(\n getMinimumBalanceSourceTokens(),\n );\n\n return allSourceTotal.gt(0) ? allSourceTotal : getSwapBalanceTotalUsd();\n };\n\n const getExactOutIntentSourceUsd = () => {\n const intentSourceUsd = (intentData?.sources ?? []).reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber((source as any).value) ?? new Decimal(0)),\n new Decimal(0),\n );\n return intentSourceUsd.gt(0) ? intentSourceUsd : undefined;\n };\n\n const getExactOutHeldDestinationUsd = () => {\n const heldDestinationToken = getHeldDestinationTokenOption();\n const value = parseFiatNumber(heldDestinationToken?.balanceInFiat);\n return value && value.gt(0) ? value : new Decimal(0);\n };\n\n const exactOutIntentIncludesHeldDestination = () => {\n const heldDestinationToken = getHeldDestinationTokenOption();\n const heldDestinationKey = getTokenSelectionKey(heldDestinationToken);\n if (!heldDestinationKey) return false;\n\n return (intentData?.sources ?? []).some((source) => {\n const chainId = source.chain?.id;\n const tokenAddress = source.token?.contractAddress;\n if (!chainId || !tokenAddress) return false;\n\n return (\n getTokenSelectionKey({\n chainId,\n contractAddress: tokenAddress,\n } as SwapTokenOption) === heldDestinationKey\n );\n });\n };\n\n const getExactOutRequiredSourceUsd = () => {\n const intentSourceUsd = getExactOutIntentSourceUsd();\n if (intentSourceUsd) return intentSourceUsd;\n return undefined;\n };\n\n const getExactOutRequiredFundingUsd = () => {\n const sourceRequiredUsd = getExactOutRequiredSourceUsd();\n if (sourceRequiredUsd) {\n const destinationCreditUsd = exactOutIntentIncludesHeldDestination()\n ? new Decimal(0)\n : getExactOutHeldDestinationUsd();\n return sourceRequiredUsd.plus(destinationCreditUsd);\n }\n\n return getExactOutRequestedUsd();\n };\n\n const getExactInSourceDeficitUsd = () => {\n if (swapType !== \"exactIn\" || fromTokens.length === 0) return undefined;\n\n return fromTokens.reduce((sum, token) => {\n const requestedAmount = parseFiatNumber(token.userAmount);\n if (!requestedAmount || requestedAmount.lte(0)) return sum;\n\n if (token.userAmountMode === \"usd\") {\n const availableUsd = parseFiatNumber(token.balanceInFiat);\n if (!availableUsd || requestedAmount.lte(availableUsd)) return sum;\n return sum.plus(requestedAmount.minus(availableUsd));\n }\n\n const availableTokenAmount = parseFiatNumber(token.balance);\n if (!availableTokenAmount || requestedAmount.lte(availableTokenAmount)) {\n return sum;\n }\n\n const missingTokenAmount = requestedAmount.minus(availableTokenAmount);\n const fiatBalance = parseFiatNumber(token.balanceInFiat);\n if (fiatBalance && availableTokenAmount.gt(0)) {\n return sum.plus(\n missingTokenAmount.mul(fiatBalance.div(availableTokenAmount)),\n );\n }\n\n return sum;\n }, new Decimal(0));\n };\n\n const buildInsufficientSourcesIssue = (error: unknown): SwapQuoteIssue => {\n const errorText = getErrorText(error);\n const details =\n (error as any)?.data?.details ?? (error as any)?.details ?? {};\n const requiredFromError =\n parseFiatNumber(\n details.requiredUsd ??\n details.requiredUSD ??\n details.requiredAmountUsd ??\n details.requiredAmount ??\n details.required,\n ) ?? parseLabeledErrorDecimal(errorText, \"required\");\n const availableFromError =\n parseFiatNumber(\n details.availableUsd ??\n details.availableUSD ??\n details.availableAmountUsd ??\n details.availableAmount ??\n details.available,\n ) ?? parseLabeledErrorDecimal(errorText, \"available\");\n const requestedUsd = getExactOutRequiredFundingUsd();\n const availableUsd = getExactOutAvailableSourceUsd();\n const exactInSourceDeficitUsd = getExactInSourceDeficitUsd();\n\n let missingUsd =\n exactInSourceDeficitUsd && exactInSourceDeficitUsd.gt(0)\n ? exactInSourceDeficitUsd\n : requiredFromError && availableFromError\n ? requiredFromError.minus(availableFromError)\n : undefined;\n\n if (\n requestedUsd &&\n (!missingUsd || missingUsd.lte(0) || missingUsd.gt(requestedUsd.mul(5)))\n ) {\n missingUsd = requestedUsd.minus(availableUsd);\n }\n\n if (missingUsd && missingUsd.gt(0)) {\n const formattedMissing =\n missingUsd.gt(0) && missingUsd.lt(0.01)\n ? \"<$0.01\"\n : formatUsdDisplay(missingUsd);\n\n return {\n type: \"insufficientSources\",\n missingUsd: missingUsd.toDecimalPlaces(2).toFixed(),\n message: `Need ${formattedMissing} more across your assets`,\n };\n }\n\n return {\n type: \"insufficientSources\",\n message: \"Add more source balance across your assets\",\n };\n };\n\n const buildExactOutSourceBalanceIssue = (\n sourceTokensOverride?: SwapTokenOption[],\n ): SwapQuoteIssue | null => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return null;\n const requestedUsd = getExactOutRequiredFundingUsd();\n const availableUsd = getExactOutAvailableSourceUsd(sourceTokensOverride);\n if (!requestedUsd || requestedUsd.lte(0) || !availableUsd) return null;\n\n const missingUsd = requestedUsd.minus(availableUsd);\n if (missingUsd.lte(0.01)) return null;\n\n const formattedMissing =\n missingUsd.gt(0) && missingUsd.lt(0.01)\n ? \"<$0.01\"\n : formatUsdDisplay(missingUsd);\n\n return {\n type: \"insufficientSources\",\n missingUsd: missingUsd.toDecimalPlaces(2).toFixed(),\n message: `Need ${formattedMissing} more across your assets`,\n };\n };\n\n const isNativeTokenAddress = (address?: string) =>\n !address ||\n address.toLowerCase() === \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\" ||\n address.toLowerCase() === \"0x0000000000000000000000000000000000000000\";\n\n const formatReadableTokenAmount = (rawAmount: bigint, decimals: number) =>\n new Decimal(rawAmount.toString())\n .div(new Decimal(10).pow(decimals))\n .toFixed();\n\n const formatReadableTokenBalanceAmount = (\n rawAmount: bigint,\n decimals: number,\n ) =>\n new Decimal(rawAmount.toString())\n .div(new Decimal(10).pow(decimals))\n .toDecimalPlaces(6)\n .toFixed();\n\n const trimDecimalString = (value: string) =>\n value.replace(/(\\.\\d*?)0+$/, \"$1\").replace(/\\.$/, \"\");\n\n const buildSourceTokenSnapshotMap = useCallback(\n (balances: UserAsset[] | null | undefined) => {\n const snapshots = new Map();\n\n for (const asset of balances ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n const chainId = breakdown.chain?.id;\n const contractAddress = breakdown.contractAddress;\n const symbol = breakdown.symbol ?? asset.symbol;\n\n if (\n !chainId ||\n !contractAddress ||\n !symbol ||\n !isSwapSupportedBySdkChainList(\n chainId,\n swapSupportedChainsAndTokens,\n )\n ) {\n continue;\n }\n\n const chainMeta = CHAIN_METADATA[chainId];\n const fiatBalance = parseFiatNumber(breakdown.balanceInFiat);\n const snapshot: SwapTokenOption = {\n balance: breakdown.balance ?? \"0\",\n balanceInFiat: fiatBalance\n ? formatUsdDisplay(fiatBalance)\n : \"$0.00\",\n chainId,\n chainLogo: chainMeta?.logo ?? breakdown.chain?.logo,\n chainName: getShortChainName(\n chainId,\n chainMeta?.name ?? breakdown.chain?.name,\n ),\n contractAddress,\n decimals: breakdown.decimals ?? asset.decimals ?? 18,\n logo: asset.logo ?? \"\",\n name: symbol,\n symbol,\n };\n snapshots.set(getTokenSelectionKey(snapshot), snapshot);\n }\n }\n\n return snapshots;\n },\n [swapSupportedChainsAndTokens],\n );\n\n const patchSourceTokensWithBalances = useCallback(\n (tokens: SwapTokenOption[], balances: UserAsset[]) => {\n const snapshots = buildSourceTokenSnapshotMap(balances);\n\n const updateToken = (token: SwapTokenOption): SwapTokenOption => {\n const preservedAmounts = {\n userAmount: token.userAmount,\n userAmountMode: token.userAmountMode,\n userAmountUsd: token.userAmountUsd,\n };\n\n if (token.isUnified) {\n const sourceTokens = (token.sourceTokens ?? []).map(updateToken);\n const totalBalance = sourceTokens.reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber(source.balance) ?? new Decimal(0)),\n new Decimal(0),\n );\n const totalFiat = sourceTokens.reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber(source.balanceInFiat) ?? new Decimal(0)),\n new Decimal(0),\n );\n\n return {\n ...token,\n ...preservedAmounts,\n balance: totalBalance.toDecimalPlaces(8).toFixed(),\n balanceInFiat: formatUsdDisplay(totalFiat),\n sourceTokens,\n };\n }\n\n const snapshot = snapshots.get(getTokenSelectionKey(token));\n if (!snapshot) {\n return {\n ...token,\n ...preservedAmounts,\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n chainLogo:\n token.chainLogo ??\n (token.chainId ? CHAIN_METADATA[token.chainId]?.logo : undefined),\n chainName: getShortChainName(token.chainId, token.chainName),\n };\n }\n\n return {\n ...token,\n ...snapshot,\n ...preservedAmounts,\n };\n };\n\n return tokens.map(updateToken);\n },\n [buildSourceTokenSnapshotMap],\n );\n\n const refreshSelectedSourceBalances = useCallback(async () => {\n const refreshedBalance = await fetchSwapBalance();\n const balances = refreshedBalance ?? swapBalance;\n if (!balances) return;\n\n setFromTokens((current) =>\n current.length === 0\n ? current\n : patchSourceTokensWithBalances(current, balances),\n );\n setSourceSelectionRevision((current) => current + 1);\n }, [fetchSwapBalance, patchSourceTokensWithBalances, swapBalance]);\n\n const receiveMaxSafetyMultiplier = new Decimal(\"0.9\");\n const currentSwapEntry =\n currentSwapId !== null\n ? swapHistory.find((entry) => entry.id === currentSwapId)\n : undefined;\n\n const scheduleTerminalBalanceRefresh = () => {\n if (terminalBalanceRefreshTimerRef.current) {\n clearTimeout(terminalBalanceRefreshTimerRef.current);\n }\n\n terminalBalanceRefreshTimerRef.current = setTimeout(() => {\n terminalBalanceRefreshTimerRef.current = null;\n void fetchSwapBalance();\n }, BALANCE_REFRESH_AFTER_TERMINAL_MS);\n };\n\n const patchSwapHistoryEntry = (\n id: string | null | undefined,\n patch: Partial,\n ) => {\n if (!id) return;\n setSwapHistory((prev) =>\n sortSwapHistoryEntries(\n prev.map((entry) => (entry.id === id ? { ...entry, ...patch } : entry)),\n ),\n );\n };\n\n const patchCurrentSwapHistoryEntry = (patch: Partial) => {\n patchSwapHistoryEntry(currentSwapIdRef.current, patch);\n };\n\n const patchCurrentIntentExplorerUrl = (url?: string | null) => {\n if (!isHttpUrl(url)) return;\n if (intentUrlRef.current === url) return;\n\n intentUrlRef.current = url;\n const intentId = extractIntentIdFromUrl(url);\n patchCurrentSwapHistoryEntry({\n intentExplorerUrl: url,\n ...(intentId ? { intentId } : {}),\n });\n };\n\n const resetExplorerUrls = () => {\n const next = { sourceExplorerUrl: null, destinationExplorerUrl: null };\n explorerUrlsRef.current = next;\n setExplorerUrls(next);\n };\n\n const mergeExplorerUrls = (\n patch: Partial<{\n sourceExplorerUrl: string | null;\n destinationExplorerUrl: string | null;\n }>,\n ) => {\n const next = { ...explorerUrlsRef.current, ...patch };\n explorerUrlsRef.current = next;\n setExplorerUrls(next);\n patchCurrentSwapHistoryEntry({\n sourceExplorerUrl: next.sourceExplorerUrl,\n finalExplorerUrl: next.destinationExplorerUrl ?? next.sourceExplorerUrl,\n });\n };\n\n const resetProgressEvents = () => {\n progressEventsRef.current = [];\n setProgressEvents((current) => (current.length === 0 ? current : []));\n setFailedProgressStep((current) => (current === null ? current : null));\n };\n\n const appendProgressEvent = (\n name: string,\n step: SwapStepType | BridgeStepType | undefined,\n defaultCompleted: boolean,\n event?: unknown,\n ) => {\n if (!step) return;\n const completed =\n typeof (step as any).completed === \"boolean\"\n ? Boolean((step as any).completed)\n : defaultCompleted;\n\n setProgressEvents((prev) => {\n const next = [\n ...prev,\n {\n id: `${Date.now()}-${prev.length}-${(step as any).typeID ?? (step as any).type ?? name}`,\n name,\n completed,\n event,\n step,\n },\n ];\n progressEventsRef.current = next;\n return next;\n });\n };\n\n const appendProgressListEvent = (\n name: string,\n stepList: Array,\n ) => {\n if (stepList.length === 0) return;\n\n setProgressEvents((prev) => {\n const next = [\n ...prev,\n {\n id: `${Date.now()}-${prev.length}-${name}`,\n name,\n completed: false,\n step: stepList[0],\n steps: stepList,\n },\n ];\n progressEventsRef.current = next;\n return next;\n });\n };\n\n const startSwapHistoryEntry = () => {\n const id = `${Date.now()}-${swapRunIdRef.current}`;\n const now = Date.now();\n const resolvedToToken =\n toToken && destinationBalance\n ? { ...toToken, balance: destinationBalance }\n : toToken;\n const entry: SwapHistoryEntry = {\n id,\n mode: activeMode,\n status: \"pending\",\n createdAt: now,\n startedAt: now,\n intentData,\n fromTokens,\n toToken: resolvedToToken,\n requestedToAmount:\n activeMode === \"deposit\" || activeMode === \"send\"\n ? previewDestinationAmount\n : undefined,\n requestedToValue:\n activeMode === \"deposit\" || activeMode === \"send\"\n ? previewToAmountUsd\n : undefined,\n recipientAddress: transferRecipientAddress,\n opportunity: selectedOpportunity,\n feeUsd: intentFeeUsd,\n sourceExplorerUrl: null,\n finalExplorerUrl: null,\n intentExplorerUrl: isHttpUrl(intentUrlRef.current)\n ? intentUrlRef.current\n : null,\n intentId: extractIntentIdFromUrl(intentUrlRef.current),\n autoRefundAvailable: false,\n };\n\n currentSwapStartedAtRef.current = 0;\n currentSwapIdRef.current = id;\n setCurrentSwapId(id);\n setSwapHistory((prev) => sortSwapHistoryEntries([entry, ...prev]));\n return id;\n };\n\n const finishCurrentSwapHistoryEntry = (\n status: \"fulfilled\" | \"failed\" | \"timeout\",\n patch: Partial = {},\n ) => {\n const now = Date.now();\n const startedAt = currentSwapStartedAtRef.current || now;\n patchSwapHistoryEntry(currentSwapIdRef.current, {\n status,\n endedAt: now,\n durationSeconds: Math.max(1, Math.round((now - startedAt) / 1000)),\n sourceExplorerUrl: explorerUrlsRef.current.sourceExplorerUrl,\n finalExplorerUrl:\n explorerUrlsRef.current.destinationExplorerUrl ??\n explorerUrlsRef.current.sourceExplorerUrl,\n ...patch,\n });\n scheduleTerminalBalanceRefresh();\n };\n\n const markSwapExecutionStarted = () => {\n if (currentSwapStartedAtRef.current > 0) return;\n const now = Date.now();\n currentSwapStartedAtRef.current = now;\n patchCurrentSwapHistoryEntry({ startedAt: now });\n };\n\n const enterSkippedSwapProgress = () => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n\n const shouldInitializeProgress = swapStepRef.current !== \"progress\";\n if (!currentSwapIdRef.current) {\n onStart?.();\n startSwapHistoryEntry();\n }\n\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setPreviewQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setSwapQuoteIssue(null);\n\n if (shouldInitializeProgress) {\n resetProgressEvents();\n swapStepsListRef.current = [];\n resetSteps();\n swapStepRef.current = \"progress\";\n setSwapStep(\"progress\");\n }\n };\n\n const cachePredictiveBaselineFromIntent = (intent: SwapIntentData) => {\n const destinationAmount = parseFiatNumber(intent.destination?.amount);\n const destinationValue = parseFiatNumber(intent.destination?.value);\n const sourceUsd = (intent.sources ?? []).reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber((source as any).value) ?? new Decimal(0)),\n new Decimal(0),\n );\n\n if (!destinationAmount || destinationAmount.lte(0)) return;\n\n const destinationUsdRate =\n destinationValue && destinationValue.gt(0)\n ? destinationValue.div(destinationAmount)\n : getUsdRateForSymbol(intent.destination?.token?.symbol);\n if (destinationUsdRate.lte(0)) return;\n\n cacheSymbolUsdRate(intent.destination?.token?.symbol, destinationUsdRate);\n\n const key = getPredictiveQuoteCacheKey();\n if (!key) return;\n\n const baseline: PredictiveQuoteBaseline = {\n destinationUsdRate: destinationUsdRate.toDecimalPlaces(18).toFixed(),\n updatedAt: Date.now(),\n };\n\n if (activeMode === \"swap\" && swapType === \"exactIn\" && sourceUsd.gt(0)) {\n baseline.exactInDestinationAmountPerSourceUsd = destinationAmount\n .div(sourceUsd)\n .toDecimalPlaces(18)\n .toFixed();\n }\n\n const resolvedDestinationValue =\n destinationValue && destinationValue.gt(0)\n ? destinationValue\n : destinationAmount.mul(destinationUsdRate);\n if (\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n resolvedDestinationValue.gt(0) &&\n sourceUsd.gt(0)\n ) {\n baseline.exactOutSourceUsdPerDestinationUsd = sourceUsd\n .div(resolvedDestinationValue)\n .toDecimalPlaces(18)\n .toFixed();\n }\n\n predictiveQuoteCacheRef.current[key] = baseline;\n };\n\n const applySwapIntent = useCallback(\n (intent: SwapIntentData) => {\n const sortedIntent = {\n ...intent,\n sources: sortIntentSourcesByUsdDesc(intent.sources ?? []),\n };\n const enrichedIntent = enrichSwapIntentTokenMetadata(sortedIntent);\n const sortedIntentSourceTokens = sortSwapTokensByUsdDesc(\n (enrichedIntent.sources ?? []).map(buildIntentSourceToken),\n );\n\n lastSwapIntentRefreshAtRef.current = Date.now();\n lastIntentSourceTokensRef.current = sortedIntentSourceTokens;\n if (\n !sourceSelectionTouched &&\n (activeMode === \"send\" ||\n (activeMode === \"deposit\" && swapType === \"exactOut\"))\n ) {\n lastAutoIntentSourceTokensRef.current = sortedIntentSourceTokens;\n }\n cacheDestinationUsdRateFromIntent(enrichedIntent);\n cachePredictiveBaselineFromIntent(enrichedIntent);\n setIntentData(enrichedIntent);\n setIntentToAmount(enrichedIntent.destination?.amount || undefined);\n setSwapQuoteIssue(null);\n\n if (\n !sourceSelectionTouched &&\n swapStepRef.current !== \"choose-swap-asset\" &&\n (activeMode === \"send\" ||\n (activeMode === \"deposit\" && swapType === \"exactOut\"))\n ) {\n syncingIntentSourcesRef.current = true;\n setFromTokens(sortedIntentSourceTokens);\n }\n\n try {\n const bridgeFees = enrichedIntent.feesAndBuffer?.bridge;\n const bridgeFeeData =\n bridgeFees && typeof bridgeFees === \"object\" ? bridgeFees : undefined;\n const collectionFee = parseFiatNumber(bridgeFeeData?.collection);\n const fulfilmentFee = parseFiatNumber(bridgeFeeData?.fulfilment);\n const executionGasFee =\n parseFiatNumber(bridgeFeeData?.caGas) ??\n (collectionFee !== undefined || fulfilmentFee !== undefined\n ? (collectionFee ?? new Decimal(0)).plus(\n fulfilmentFee ?? new Decimal(0),\n )\n : undefined);\n const bridgeGasSuppliedFee = parseFiatNumber(\n bridgeFeeData?.gasSupplied,\n );\n const destinationGasSuppliedFee =\n getIntentDestinationGasUsdValue(enrichedIntent);\n const gasSuppliedFee =\n bridgeGasSuppliedFee ?? destinationGasSuppliedFee;\n const bridgeComponentsTotal = bridgeFeeData\n ? [\n executionGasFee,\n parseFiatNumber(bridgeFeeData.protocol),\n parseFiatNumber(bridgeFeeData.solver),\n gasSuppliedFee,\n ].reduce(\n (sum, value) => sum.plus(value ?? new Decimal(0)),\n new Decimal(0),\n )\n : undefined;\n const rawBridgeTotal =\n typeof bridgeFees === \"string\"\n ? parseFiatNumber(bridgeFees)\n : parseFiatNumber(bridgeFeeData?.total);\n const bridgeTotal =\n rawBridgeTotal &&\n !bridgeGasSuppliedFee &&\n destinationGasSuppliedFee &&\n destinationGasSuppliedFee.gt(0)\n ? rawBridgeTotal.plus(destinationGasSuppliedFee)\n : (rawBridgeTotal ??\n (bridgeComponentsTotal && bridgeComponentsTotal.gt(0)\n ? bridgeComponentsTotal\n : destinationGasSuppliedFee));\n\n if (bridgeTotal !== undefined) {\n setIntentFeeUsd(\n bridgeTotal.gt(0) ? bridgeTotal.toDecimalPlaces(6).toFixed() : \"0\",\n );\n } else {\n setIntentFeeUsd(undefined);\n }\n } catch (err) {\n console.warn(\"Could not resolve bridge fee total\", err);\n setIntentFeeUsd(undefined);\n }\n },\n [\n activeMode,\n fromTokens,\n getFiatValue,\n sourceSelectionTouched,\n swapType,\n swapBalance,\n swapSupportedChainsAndTokens,\n supportedChainsAndTokens,\n toToken,\n ],\n );\n\n const handleSwapIntentCallback = useCallback(\n (data: any, runId: number, quoteInputKey: string) => {\n const { intent, allow, deny, refresh } = data;\n const bridgeProvider = normalizeBridgeProvider(\n data?.bridgeProvider ??\n intent?.bridgeProvider ??\n intent?.normalizedIntent?.bridgeProvider ??\n intent?.swap?.bridgeProvider,\n );\n const intentWithBridgeProvider = normalizeRenderableSwapIntentData(\n intent,\n bridgeProvider,\n );\n logSdkIntentEvent(\"onIntent\", data, {\n bridgeProvider,\n currentRunId: swapRunIdRef.current,\n normalizedIntent: intentWithBridgeProvider,\n isCurrentRun: swapRunIdRef.current === runId,\n quoteInputKey,\n runId,\n });\n if (swapRunIdRef.current !== runId) {\n logSdkIntentEvent(\"ignored stale onIntent\", data, {\n currentRunId: swapRunIdRef.current,\n quoteInputKey,\n runId,\n });\n deny();\n return;\n }\n if (quoteInputKey && activeQuoteInputKeyRef.current !== quoteInputKey) {\n logSdkIntentEvent(\"ignored stale quote input onIntent\", data, {\n currentQuoteInputKey: activeQuoteInputKeyRef.current,\n quoteInputKey,\n runId,\n });\n deny();\n return;\n }\n if (!intentWithBridgeProvider) {\n console.warn(\"[NexusWidget SDK][intent] Unsupported intent shape\", {\n intent,\n raw: data,\n });\n finishIntentFetchTiming(runId, \"failed\");\n deny();\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setTxError(\"Quote unavailable\");\n return;\n }\n const resolvedQuoteInputKey = quoteInputKey;\n const normalizedRefresh =\n typeof refresh === \"function\"\n ? async (...args: unknown[]) => {\n const refreshed = await refresh(...args);\n const refreshedBridgeProvider = normalizeBridgeProvider(\n refreshed?.bridgeProvider ??\n refreshed?.normalizedIntent?.bridgeProvider ??\n refreshed?.swap?.bridgeProvider ??\n bridgeProvider,\n );\n return (\n normalizeRenderableSwapIntentData(\n refreshed,\n refreshedBridgeProvider,\n ) ?? refreshed\n );\n }\n : refresh;\n finishIntentFetchTiming(runId);\n providerSwapIntent.current = {\n intent: intentWithBridgeProvider as any,\n allow,\n deny,\n refresh: normalizedRefresh,\n };\n swapIntentRef.current = {\n intent: intentWithBridgeProvider,\n allow,\n deny,\n refresh: normalizedRefresh,\n runId,\n quoteInputKey: resolvedQuoteInputKey,\n };\n flushSync(() => {\n applySwapIntent(intentWithBridgeProvider);\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n });\n },\n [applySwapIntent, finishIntentFetchTiming, providerSwapIntent],\n );\n\n // Deposit-specific\n const [selectedOpportunity, setSelectedOpportunity] = useState<\n NexusWidgetDepositOpportunityConfig | undefined\n >(() => (activeMode === \"deposit\" ? configuredDeposit : undefined));\n const selectedOpportunityIdentity =\n getDepositConfigIdentity(selectedOpportunity);\n const [depositAmountMode, setDepositAmountMode] = useState<\"token\" | \"usd\">(\n \"token\",\n );\n const [depositSourceFilter, setDepositSourceFilter] =\n useState(\"all\");\n\n useEffect(() => {\n const immediateIssue = buildReceiveAmountIssue();\n applyReceiveAmountIssue(immediateIssue);\n\n if (!toToken || !getDestinationReceiveLimitUsd(toToken)) return;\n if (!parseFiatNumber(amount)?.gt(0)) return;\n if (getImmediateDestinationReceiveUsdRate(toToken)?.gt(0)) return;\n\n let cancelled = false;\n void resolveUsdRateForToken(toToken)\n .then((resolvedRate) => {\n if (cancelled) return;\n const issue = buildReceiveAmountIssue({\n destinationRate: resolvedRate.gt(0) ? resolvedRate : undefined,\n });\n applyReceiveAmountIssue(issue);\n })\n .catch(() => {\n if (!cancelled) {\n applyReceiveAmountIssue(buildReceiveAmountIssue());\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [\n activeMode,\n amount,\n depositAmountMode,\n fromTokens,\n swapType,\n toToken?.chainId,\n toToken?.chainName,\n toToken?.contractAddress,\n toToken?.priceUSD,\n toToken?.symbol,\n ]);\n\n const trackDeposit = useCallback(\n (event: string, props?: Record) => {\n const analytics = nexusSDK?.analytics;\n if (!analytics) return;\n analytics.track(event, {\n widgetSessionId: widgetSessionIdRef.current,\n widgetAttemptId: widgetAttemptIdRef.current,\n opportunityProtocol: selectedOpportunity?.protocol ?? null,\n destinationChainId: selectedOpportunity?.chainId ?? null,\n destinationToken: selectedOpportunity?.tokenSymbol ?? null,\n ...props,\n });\n },\n [nexusSDK, selectedOpportunity],\n );\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (!nexusSDK?.analytics) return;\n if (widgetOpenedFiredRef.current) return;\n widgetOpenedFiredRef.current = true;\n widgetOpenedTsRef.current = Date.now();\n rotateAttempt();\n trackDeposit(\"deposit_widget_opened\", {\n embed: Boolean(embed),\n depositConfigured: Boolean(configuredDeposit),\n prefillAmountPresent: Boolean(config.prefill?.amount),\n });\n }, [\n activeMode,\n nexusSDK,\n embed,\n configuredDeposit,\n config.prefill,\n rotateAttempt,\n trackDeposit,\n ]);\n\n useEffect(() => {\n analyticsRef.current = nexusSDK?.analytics ?? null;\n }, [nexusSDK]);\n\n useEffect(() => {\n selectedOpportunityRef.current = selectedOpportunity;\n }, [selectedOpportunity]);\n\n useEffect(() => {\n return () => {\n if (!widgetOpenedFiredRef.current) return;\n const analytics = analyticsRef.current;\n if (!analytics) return;\n const opp = selectedOpportunityRef.current;\n analytics.track(\"deposit_widget_closed\", {\n widgetSessionId: widgetSessionIdRef.current,\n widgetAttemptId: widgetAttemptIdRef.current,\n opportunityProtocol: opp?.protocol ?? null,\n lastStep: swapStepRef.current,\n reachedTerminal: reachedTerminalRef.current,\n hadSimulationSuccess: hadSimulationSuccessRef.current,\n hadPreviewViewed: hadPreviewViewedRef.current,\n timeInWidgetMs: Date.now() - widgetOpenedTsRef.current,\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const toTokenFromOpportunity = (\n opp: NexusWidgetDepositOpportunityMetadata,\n ): SwapTokenOption => {\n const citreaToken = findCitreaReceiveToken({\n address: opp.tokenAddress,\n chainId: opp.chainId,\n symbol: opp.tokenSymbol,\n });\n const chainTokens = supportedChainsAndTokens?.find(\n (chain) => chain.id === opp.chainId,\n )?.tokens;\n const matchedToken = chainTokens?.find(\n (token) =>\n token.contractAddress.toLowerCase() ===\n opp.tokenAddress.toLowerCase() || token.symbol === opp.tokenSymbol,\n );\n const tokenSymbol =\n citreaToken?.symbol ?? matchedToken?.symbol ?? opp.tokenSymbol;\n const tokenMeta =\n TOKEN_METADATA[tokenSymbol as keyof typeof TOKEN_METADATA];\n\n return {\n chainId: opp.chainId,\n contractAddress: citreaToken?.contractAddress ?? opp.tokenAddress,\n symbol: tokenSymbol,\n name: matchedToken?.name || citreaToken?.name || tokenSymbol,\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n decimals:\n matchedToken?.decimals ??\n citreaToken?.decimals ??\n opp.tokenDecimals ??\n tokenMeta?.decimals ??\n 18,\n logo:\n opp.tokenLogo ||\n matchedToken?.logo ||\n citreaToken?.logo ||\n tokenMeta?.logo,\n chainName: getShortChainName(\n opp.chainId,\n CHAIN_METADATA[opp.chainId]?.name ?? citreaToken?.chainName,\n ),\n chainLogo: CHAIN_METADATA[opp.chainId]?.logo ?? citreaToken?.chainLogo,\n };\n };\n\n const getDestinationBalanceFromSwapBalances = (token?: SwapTokenOption) => {\n if (!token?.chainId || !token.contractAddress) return null;\n\n const targetAddress = token.contractAddress.toLowerCase();\n const targetSymbol = token.symbol.toUpperCase();\n\n for (const asset of swapBalance ?? []) {\n for (const breakdown of asset.breakdown ?? []) {\n if (breakdown.chain?.id !== token.chainId) continue;\n\n const breakdownAddress = breakdown.contractAddress?.toLowerCase();\n const addressMatches =\n (breakdownAddress && breakdownAddress === targetAddress) ||\n (isNativeTokenAddress(breakdownAddress) &&\n isNativeTokenAddress(targetAddress));\n const symbolMatches =\n (breakdown.symbol ?? asset.symbol ?? \"\").toUpperCase() ===\n targetSymbol;\n\n if (!addressMatches && !symbolMatches) continue;\n\n const balance = parseFiatNumber(breakdown.balance);\n if (!balance) return null;\n\n return balance.toFixed();\n }\n }\n\n return null;\n };\n\n const resolvePrefillToken = useCallback(\n (pair?: RuntimeDestinationPair) => {\n if (!pair?.token || !pair.chain) return undefined;\n\n const normalizeAddress = (address?: string) => {\n if (!address) return \"\";\n return isNativeTokenAddress(address)\n ? zeroAddress\n : address.toLowerCase();\n };\n const targetAddress = normalizeAddress(pair.token);\n\n const balanceToken = deriveTokenOptions(\n swapBalance ?? [],\n swapSupportedChainsAndTokens,\n ).find(\n (token) =>\n token.chainId === pair.chain &&\n normalizeAddress(token.contractAddress) === targetAddress,\n );\n if (balanceToken) return balanceToken;\n\n const chain = supportedChainsAndTokens?.find(\n (item) => item.id === pair.chain,\n );\n const matchedToken = chain?.tokens?.find(\n (token) => normalizeAddress(token.contractAddress) === targetAddress,\n );\n const citreaToken = findCitreaReceiveToken({\n address: pair.token,\n chainId: pair.chain,\n });\n const tokenAddressSymbol = Object.entries(\n TOKEN_CONTRACT_ADDRESSES as Record>,\n ).find(\n ([, addresses]) =>\n normalizeAddress(addresses[pair.chain]) === targetAddress,\n )?.[0];\n const chainMeta = CHAIN_METADATA[pair.chain];\n const isNativePrefill = isNativeTokenAddress(pair.token);\n const tokenSymbol =\n matchedToken?.symbol ??\n citreaToken?.symbol ??\n pair.symbol ??\n tokenAddressSymbol ??\n (isNativePrefill ? chainMeta?.nativeCurrency?.symbol : undefined) ??\n \"Token\";\n const tokenMeta =\n TOKEN_METADATA[tokenSymbol as keyof typeof TOKEN_METADATA];\n\n if (\n !chain &&\n !matchedToken &&\n !citreaToken &&\n !tokenAddressSymbol &&\n !pair.symbol &&\n !isNativePrefill\n ) {\n return undefined;\n }\n\n return {\n chainId: pair.chain,\n contractAddress: citreaToken?.contractAddress ?? pair.token,\n symbol: tokenSymbol,\n name: matchedToken?.name || citreaToken?.name || tokenSymbol,\n balance: \"0\",\n balanceInFiat: \"$0.00\",\n decimals:\n matchedToken?.decimals ??\n citreaToken?.decimals ??\n pair.decimals ??\n tokenMeta?.decimals ??\n (isNativePrefill ? chainMeta?.nativeCurrency?.decimals : undefined) ??\n 18,\n logo:\n matchedToken?.logo ||\n citreaToken?.logo ||\n pair.logo ||\n tokenMeta?.logo,\n chainName: getShortChainName(\n pair.chain,\n chain?.name ?? chainMeta?.name ?? citreaToken?.chainName,\n ),\n chainLogo: chainMeta?.logo ?? chain?.logo ?? citreaToken?.chainLogo,\n } satisfies SwapTokenOption;\n },\n [supportedChainsAndTokens, swapBalance],\n );\n\n useEffect(() => {\n if (activeMode !== \"swap\") return;\n\n const sourcePrefill = config.prefill?.source;\n const destinationPrefill = config.prefill?.destination;\n if (!sourcePrefill && !destinationPrefill) return;\n\n const prefillKey = [\n sourcePrefill\n ? `source:${sourcePrefill.chain}:${sourcePrefill.token.toLowerCase()}`\n : \"\",\n destinationPrefill\n ? `destination:${destinationPrefill.chain}:${destinationPrefill.token.toLowerCase()}`\n : \"\",\n config.prefill?.amount ? `amount:${config.prefill.amount}` : \"\",\n ].join(\"|\");\n\n if (appliedTokenPrefillRef.current === prefillKey) return;\n\n const sourceToken = resolvePrefillToken(sourcePrefill);\n const destinationToken = resolvePrefillToken(destinationPrefill);\n\n if (sourcePrefill && !sourceToken) return;\n if (destinationPrefill && !destinationToken) return;\n\n if (sourceToken) {\n setFromTokens((current) => {\n const nextSourceToken = {\n ...sourceToken,\n userAmount: config.prefill?.amount ?? \"\",\n };\n const currentSourceToken = current[0];\n if (\n current.length === 1 &&\n isSameTokenSelection(currentSourceToken, nextSourceToken) &&\n currentSourceToken.userAmount === nextSourceToken.userAmount\n ) {\n return current;\n }\n return [nextSourceToken];\n });\n setSourceSelectionTouched(true);\n }\n if (destinationToken) {\n setToToken((current) =>\n isSameTokenSelection(current, destinationToken)\n ? current\n : destinationToken,\n );\n }\n setSwapType(\"exactIn\");\n appliedTokenPrefillRef.current = prefillKey;\n }, [\n activeMode,\n config.prefill?.amount,\n config.prefill?.destination?.chain,\n config.prefill?.destination?.decimals,\n config.prefill?.destination?.logo,\n config.prefill?.destination?.symbol,\n config.prefill?.destination?.token,\n config.prefill?.source?.chain,\n config.prefill?.source?.decimals,\n config.prefill?.source?.logo,\n config.prefill?.source?.symbol,\n config.prefill?.source?.token,\n resolvePrefillToken,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"send\") return;\n\n const sendPrefill =\n config.prefill?.token && config.prefill?.chain\n ? {\n token: config.prefill.token,\n chain: config.prefill.chain,\n }\n : config.prefill?.destination;\n if (!sendPrefill) return;\n\n const prefillKey = `send:${sendPrefill.chain}:${sendPrefill.token.toLowerCase()}`;\n if (appliedTokenPrefillRef.current === prefillKey) return;\n\n const token = resolvePrefillToken(sendPrefill);\n if (!token) return;\n\n setToToken(token);\n setSwapType(\"exactOut\");\n appliedTokenPrefillRef.current = prefillKey;\n }, [\n activeMode,\n config.prefill?.chain,\n config.prefill?.destination?.chain,\n config.prefill?.destination?.decimals,\n config.prefill?.destination?.logo,\n config.prefill?.destination?.symbol,\n config.prefill?.destination?.token,\n config.prefill?.token,\n resolvePrefillToken,\n ]);\n\n useEffect(() => {\n if (config.prefill?.amount) setAmount(config.prefill.amount);\n if (config.prefill?.recipient)\n setRecipientAddress(config.prefill.recipient);\n }, [config.prefill?.amount, config.prefill?.recipient]);\n\n useEffect(() => {\n setDestinationBalance(null);\n\n const balanceToken =\n toToken ??\n (activeMode === \"deposit\" && selectedOpportunity\n ? toTokenFromOpportunity(selectedOpportunity)\n : undefined);\n\n if (!balanceToken?.chainId || !ownerAddress) return;\n\n const swapBalanceValue =\n getDestinationBalanceFromSwapBalances(balanceToken);\n if (swapBalanceValue) {\n setDestinationBalance(swapBalanceValue);\n }\n }, [\n activeMode,\n ownerAddress,\n selectedOpportunity?.chainId,\n selectedOpportunity?.tokenAddress,\n selectedOpportunity?.tokenLogo,\n selectedOpportunity?.tokenSymbol,\n swapBalance,\n toToken?.chainId,\n toToken?.chainName,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.symbol,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\" || !configuredDeposit) return;\n setSelectedOpportunity((current) =>\n isSameDepositConfig(current, configuredDeposit)\n ? current\n : configuredDeposit,\n );\n setSwapType(\"exactOut\");\n setToToken((current) => {\n const next = {\n ...toTokenFromOpportunity(configuredDeposit),\n balance: current?.balance ?? \"0\",\n balanceInFiat: current?.balanceInFiat ?? \"$0.00\",\n };\n if (\n current &&\n current.chainId === next.chainId &&\n current.contractAddress.toLowerCase() ===\n next.contractAddress.toLowerCase() &&\n current.symbol === next.symbol &&\n current.decimals === next.decimals &&\n current.logo === next.logo &&\n current.chainLogo === next.chainLogo &&\n current.chainName === next.chainName &&\n current.balance === next.balance &&\n current.balanceInFiat === next.balanceInFiat\n ) {\n return current;\n }\n return next;\n });\n }, [\n activeMode,\n configuredDepositIdentity,\n configuredDeposit?.chainId,\n configuredDeposit?.tokenAddress,\n configuredDeposit?.tokenLogo,\n configuredDeposit?.tokenSymbol,\n supportedChainsAndTokens,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\" || !selectedOpportunity) return;\n setToToken((current) => {\n const next = {\n ...toTokenFromOpportunity(selectedOpportunity),\n balance: current?.balance ?? \"0\",\n balanceInFiat: current?.balanceInFiat ?? \"$0.00\",\n };\n if (\n current &&\n current.chainId === next.chainId &&\n current.contractAddress.toLowerCase() ===\n next.contractAddress.toLowerCase() &&\n current.symbol === next.symbol &&\n current.decimals === next.decimals &&\n current.logo === next.logo &&\n current.chainLogo === next.chainLogo &&\n current.chainName === next.chainName &&\n current.balance === next.balance &&\n current.balanceInFiat === next.balanceInFiat\n ) {\n return current;\n }\n return next;\n });\n }, [activeMode, selectedOpportunity, supportedChainsAndTokens]);\n\n useEffect(() => {\n if (activeMode !== \"send\") return;\n setSwapType(\"exactOut\");\n }, [activeMode]);\n\n useEffect(() => {\n if (activeMode === \"swap\" && swapType !== \"exactIn\") {\n setSwapType(\"exactIn\");\n }\n }, [activeMode, swapType]);\n\n useEffect(() => {\n if (!toToken?.symbol) return;\n if (getFiatValue(1, toToken.symbol) > 0) return;\n\n let cancelled = false;\n void resolveTokenUsdRate(toToken.symbol).catch((error) => {\n if (!cancelled) {\n console.warn(\"Unable to resolve Nexus Widget token USD rate\", {\n symbol: toToken.symbol,\n error,\n });\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [activeMode, getFiatValue, resolveTokenUsdRate, toToken?.symbol]);\n\n // Balance helpers\n const activeBalanceArray = swapBalance;\n const selectedToken = config.prefill?.token ?? \"USDC\";\n const currentAsset =\n activeBalanceArray?.find((a) => a.symbol === selectedToken) ||\n activeBalanceArray?.[0];\n const maxBalance = currentAsset?.balance\n ? String(currentAsset.balance)\n : undefined;\n const usdValue = getFiatValue(\n Number(amount) || 0,\n currentAsset?.symbol || \"USDC\",\n );\n const getDepositTokenUsdRate = () => {\n if (selectedOpportunity?.tokenSymbol) {\n const fiat = getFiatValue(1, selectedOpportunity.tokenSymbol);\n if (Number.isFinite(fiat) && fiat > 0) {\n return new Decimal(fiat);\n }\n }\n\n if (toToken) {\n const tokenRate = getTokenUsdRate(toToken);\n if (tokenRate.gt(0)) return tokenRate;\n }\n\n return getCachedDestinationUsdRate(toToken) ?? new Decimal(0);\n };\n const getDepositTokenAmountForQuote = () => {\n const parsedAmount = parseFiatNumber(amount) ?? new Decimal(0);\n if (parsedAmount.lte(0)) return undefined;\n if (depositAmountMode === \"token\") return parsedAmount;\n\n const rate = getDepositTokenUsdRate();\n if (rate.lte(0)) return undefined;\n return parsedAmount.div(rate);\n };\n const depositTokenAmountForQuote = getDepositTokenAmountForQuote();\n const depositQuoteAmountKey = depositTokenAmountForQuote?.toFixed() ?? \"\";\n const depositUsdDecimal =\n depositAmountMode === \"usd\"\n ? (parseFiatNumber(amount) ?? new Decimal(0))\n : depositTokenAmountForQuote\n ? depositTokenAmountForQuote.mul(getDepositTokenUsdRate())\n : new Decimal(0);\n const depositUsdDisplay = depositUsdDecimal.toDecimalPlaces(2).toFixed();\n const depositTokenDisplay =\n depositTokenAmountForQuote\n ?.toDecimalPlaces(\n getCappedTokenDisplayDecimals(toToken?.decimals),\n Decimal.ROUND_DOWN,\n )\n .toFixed() ?? \"0\";\n const isExactOutMode = activeMode === \"deposit\" || activeMode === \"send\";\n const getActiveTotalBalanceUsd = () =>\n isExactOutMode\n ? getExactOutTotalSourceBalanceUsd()\n : getSwapBalanceTotalUsd();\n const getTotalBalancePercentUsdAmount = (pct: number) => {\n const ratio =\n isExactOutMode && pct === 100\n ? receiveMaxSafetyMultiplier\n : new Decimal(pct).div(100);\n return getActiveTotalBalanceUsd().mul(ratio);\n };\n const getExactOutDestinationUsdRate = (token: SwapTokenOption) => {\n if (activeMode === \"deposit\") {\n return getDepositTokenUsdRate();\n }\n return getTokenUsdRate(token);\n };\n const getExactOutPercentAmountFromBalance = (\n token: SwapTokenOption,\n pct: number,\n preferUsd: boolean,\n ) => {\n const usdAmount = getTotalBalancePercentUsdAmount(pct);\n if (usdAmount.lte(0)) return undefined;\n\n if (preferUsd) {\n return {\n amount: usdAmount.toDecimalPlaces(2, Decimal.ROUND_DOWN).toFixed(),\n mode: \"usd\" as const,\n };\n }\n\n const rate = getExactOutDestinationUsdRate(token);\n if (rate.lte(0)) return undefined;\n\n return {\n amount: usdAmount\n .div(rate)\n .toDecimalPlaces(\n getCappedTokenDisplayDecimals(token.decimals),\n Decimal.ROUND_DOWN,\n )\n .toFixed(),\n mode: \"token\" as const,\n };\n };\n const depositSourceTargetUsdKey =\n activeMode === \"deposit\"\n ? (getDepositSourceTargetUsd()?.toFixed() ?? \"\")\n : \"\";\n const normalizedQuoteAmountKey = parseFiatNumber(amount)?.toFixed() ?? \"\";\n const quoteRecipientKey =\n activeMode === \"swap\"\n ? effectiveRecipientAddress\n : activeMode === \"send\"\n ? recipientAddress\n : \"\";\n const activeQuoteInputKey = [\n activeMode,\n swapType,\n normalizedQuoteAmountKey,\n toTokenQuoteKey,\n quoteRecipientKey.toLowerCase(),\n activeMode === \"swap\" ? fromTokensQuoteKey : \"\",\n activeMode === \"deposit\"\n ? [\n depositAmountMode,\n depositQuoteAmountKey,\n selectedOpportunityIdentity,\n depositSourceTargetUsdKey,\n depositSourceFilter,\n sourceSelectionTouched ? \"manual\" : \"auto\",\n sourceSelectionRevision,\n exactOutQuoteSourceMode,\n ].join(\":\")\n : \"\",\n activeMode === \"send\"\n ? [\n sourceSelectionTouched ? \"manual\" : \"auto\",\n sourceSelectionRevision,\n exactOutQuoteSourceMode,\n ].join(\":\")\n : \"\",\n ].join(\"|\");\n\n const exactOutAutoSourceInputKey = [\n activeMode,\n normalizedQuoteAmountKey,\n toTokenQuoteKey,\n quoteRecipientKey.toLowerCase(),\n activeMode === \"deposit\"\n ? [\n depositAmountMode,\n depositQuoteAmountKey,\n selectedOpportunityIdentity,\n depositSourceTargetUsdKey,\n ].join(\":\")\n : \"\",\n ].join(\"|\");\n\n activeQuoteInputKeyRef.current = activeQuoteInputKey;\n\n useEffect(() => {\n lastAutoIntentSourceTokensRef.current = [];\n }, [exactOutAutoSourceInputKey]);\n\n useEffect(() => {\n setTxError(null);\n }, [activeQuoteInputKey]);\n const hasCurrentQuoteIntent = Boolean(\n intentData &&\n swapIntentRef.current &&\n swapIntentRef.current.runId === swapRunIdRef.current &&\n swapIntentRef.current.quoteInputKey === activeQuoteInputKey,\n );\n\n useEffect(() => {\n if (swapStep !== \"idle\") return;\n if (!hasCurrentQuoteIntent) return;\n if (sourceSelectionTouched) return;\n if (\n activeMode !== \"send\" &&\n !(activeMode === \"deposit\" && swapType === \"exactOut\")\n ) {\n return;\n }\n\n const nextTokens = lastIntentSourceTokensRef.current;\n if (nextTokens.length === 0) return;\n\n setFromTokens((current) => {\n if (\n getSourceTokenListSyncKey(current) ===\n getSourceTokenListSyncKey(nextTokens)\n ) {\n return current;\n }\n\n syncingIntentSourcesRef.current = true;\n return nextTokens;\n });\n }, [\n activeMode,\n hasCurrentQuoteIntent,\n sourceSelectionTouched,\n swapStep,\n swapType,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (!nexusSDK?.analytics) return;\n const parsed = parseFiatNumber(amount);\n if (!parsed || parsed.lte(0)) return;\n if (amount === amountEnteredLastValueRef.current) return;\n const timeout = setTimeout(() => {\n amountEnteredLastValueRef.current = amount;\n trackDeposit(\"deposit_amount_entered\", {\n amountToken: depositTokenDisplay,\n amountUsd: Number(depositUsdDisplay) || 0,\n inputMethod: lastInputMethodRef.current,\n });\n lastInputMethodRef.current = \"typed\";\n }, 500);\n return () => clearTimeout(timeout);\n }, [\n amount,\n activeMode,\n nexusSDK,\n depositTokenDisplay,\n depositUsdDisplay,\n trackDeposit,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (intentData) hadSimulationSuccessRef.current = true;\n }, [intentData, activeMode]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (sourceSelectionTouched) return;\n previousAutoSourceCountRef.current = (intentData?.sources ?? []).length;\n }, [intentData, activeMode, sourceSelectionTouched]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n const prev = prevSourceTouchedRef.current;\n const curr = sourceSelectionTouched;\n if (prev === curr) return;\n prevSourceTouchedRef.current = curr;\n if (!prev && curr) {\n trackDeposit(\"deposit_source_selection_changed\", {\n sourceCount: fromTokens.length,\n sourceChainIds: fromTokens.map((t) => t.chainId).filter(Boolean),\n sourceTokenSymbols: fromTokens.map((t) => t.symbol).filter(Boolean),\n previousSourceCount: previousAutoSourceCountRef.current,\n });\n } else if (prev && !curr) {\n trackDeposit(\"deposit_source_selection_reverted_to_auto\", {\n previousSourceCount: fromTokens.length,\n });\n }\n }, [sourceSelectionTouched, activeMode, fromTokens, trackDeposit]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (swapStep !== \"preview-intent\") return;\n if (intentLoading) return;\n if (!intentData) return;\n if (hadPreviewViewedRef.current) return;\n hadPreviewViewedRef.current = true;\n previewViewedTsRef.current = Date.now();\n trackDeposit(\"deposit_preview_viewed\", {\n totalFeeUsd: Number(intentFeeUsd) || 0,\n toAmountUsd: Number(depositUsdDisplay) || 0,\n sourceCount: (intentData?.sources ?? []).length,\n });\n }, [\n swapStep,\n intentLoading,\n intentData,\n activeMode,\n intentFeeUsd,\n depositUsdDisplay,\n trackDeposit,\n ]);\n const requiredDestinationTokenAmount =\n activeMode === \"deposit\"\n ? depositTokenAmountForQuote\n : activeMode === \"send\"\n ? parseFiatNumber(amount)\n : undefined;\n const canRefreshExactOutQuote = () =>\n activeMode === \"deposit\"\n ? Boolean(\n hasPositiveDecimalInput(amount) &&\n toToken &&\n selectedOpportunity &&\n depositTokenAmountForQuote &&\n depositTokenAmountForQuote.gt(0),\n )\n : activeMode === \"send\"\n ? Boolean(hasPositiveDecimalInput(amount) && toToken)\n : false;\n const invalidateExactOutQuoteForRefresh = (options?: {\n sourceTokens?: SwapTokenOption[];\n }) => {\n immediateQuoteAfterSourceEditRef.current = true;\n const receiveIssue = buildReceiveAmountIssue({\n sourceTokens: options?.sourceTokens,\n });\n applyReceiveAmountIssue(receiveIssue);\n const configuredIssue = buildConfiguredAmountIssue();\n if (configuredIssue) {\n clearPreviewForBlockingAmountIssue();\n }\n const sourceBalanceIssue = buildExactOutSourceBalanceIssue(\n options?.sourceTokens,\n );\n if (sourceBalanceIssue) {\n clearPreviewForBlockingAmountIssue();\n setSwapQuoteIssue(sourceBalanceIssue);\n }\n const shouldLoadQuote = Boolean(\n !receiveIssue &&\n !configuredIssue &&\n !sourceBalanceIssue &&\n nexusSDK &&\n canRefreshExactOutQuote(),\n );\n if (!receiveIssue && !configuredIssue && !sourceBalanceIssue) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: shouldLoadQuote });\n }\n if (shouldLoadQuote) {\n setQuoteRefreshing(true);\n setTxError(null);\n setSwapQuoteIssue(null);\n }\n return shouldLoadQuote;\n };\n\n useEffect(() => {\n if (\n activeMode !== \"swap\" ||\n swapStep !== \"idle\" ||\n swapType !== \"exactIn\"\n ) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current,\n );\n return;\n }\n\n const sources = getPredictiveExactInSourceTokens();\n const key = getPredictiveQuoteCacheKey();\n if (!toToken || sources.length === 0 || !key) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current,\n );\n return;\n }\n\n const runId = ++predictiveQuoteRunRef.current;\n let cancelled = false;\n\n void (async () => {\n const baseline = predictiveQuoteCacheRef.current[key];\n const cachedDestinationRate = parseFiatNumber(\n baseline?.destinationUsdRate,\n );\n const destinationRate =\n cachedDestinationRate && cachedDestinationRate.gt(0)\n ? cachedDestinationRate\n : await resolveUsdRateForToken(toToken);\n\n if (cancelled || runId !== predictiveQuoteRunRef.current) return;\n if (destinationRate.lte(0)) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current,\n );\n return;\n }\n\n let sourceUsd = new Decimal(0);\n for (const source of sources) {\n const sourceAmount =\n parseFiatNumber(source.userAmount) ?? new Decimal(0);\n if (sourceAmount.lte(0)) continue;\n\n if (source.userAmountMode === \"usd\") {\n sourceUsd = sourceUsd.plus(sourceAmount);\n continue;\n }\n\n const sourceRate = await resolveUsdRateForToken(source);\n if (cancelled || runId !== predictiveQuoteRunRef.current) return;\n if (sourceRate.lte(0)) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current,\n );\n return;\n }\n sourceUsd = sourceUsd.plus(sourceAmount.mul(sourceRate));\n }\n\n if (sourceUsd.lte(0)) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactIn\" ? null : current,\n );\n return;\n }\n\n const cachedAmountPerSourceUsd = parseFiatNumber(\n baseline?.exactInDestinationAmountPerSourceUsd,\n );\n const predictedDestinationAmount =\n cachedAmountPerSourceUsd && cachedAmountPerSourceUsd.gt(0)\n ? sourceUsd.mul(cachedAmountPerSourceUsd)\n : sourceUsd\n .mul(BASIS_POINTS - PREDICTIVE_EXACT_IN_DISCOUNT_BPS)\n .div(BASIS_POINTS)\n .div(destinationRate);\n const predictedDestinationUsd =\n cachedAmountPerSourceUsd && cachedAmountPerSourceUsd.gt(0)\n ? predictedDestinationAmount.mul(destinationRate)\n : sourceUsd\n .mul(BASIS_POINTS - PREDICTIVE_EXACT_IN_DISCOUNT_BPS)\n .div(BASIS_POINTS);\n\n if (\n cancelled ||\n runId !== predictiveQuoteRunRef.current ||\n predictedDestinationAmount.lte(0)\n ) {\n return;\n }\n\n setPredictiveQuote({\n key,\n mode: \"exactIn\",\n toAmount: getPredictiveDisplayAmount(\n predictedDestinationAmount,\n toToken,\n ),\n toUsd: predictedDestinationUsd.toDecimalPlaces(6).toFixed(),\n });\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n activeMode,\n amount,\n fromTokens,\n swapStep,\n swapType,\n toToken?.chainId,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.symbol,\n ]);\n\n useEffect(() => {\n if (\n (activeMode !== \"deposit\" && activeMode !== \"send\") ||\n swapStep !== \"idle\" ||\n swapType !== \"exactOut\" ||\n !nexusSDK\n ) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactOut\" ? null : current,\n );\n return;\n }\n\n const parsedAmount = parseFiatNumber(amount);\n const key = getPredictiveQuoteCacheKey();\n if (\n !toToken ||\n !parsedAmount ||\n parsedAmount.lte(0) ||\n !key ||\n (activeMode === \"deposit\" && !selectedOpportunity)\n ) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactOut\" ? null : current,\n );\n return;\n }\n\n const runId = ++predictiveQuoteRunRef.current;\n let cancelled = false;\n\n void (async () => {\n const baseline = predictiveQuoteCacheRef.current[key];\n const cachedDestinationRate = parseFiatNumber(\n baseline?.destinationUsdRate,\n );\n const destinationRate =\n cachedDestinationRate && cachedDestinationRate.gt(0)\n ? cachedDestinationRate\n : await resolveUsdRateForToken(toToken);\n\n if (cancelled || runId !== predictiveQuoteRunRef.current) return;\n if (destinationRate.lte(0)) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactOut\" ? null : current,\n );\n return;\n }\n\n const destinationAmount =\n activeMode === \"deposit\" && depositAmountMode === \"usd\"\n ? parsedAmount.div(destinationRate)\n : parsedAmount;\n const destinationUsd =\n activeMode === \"deposit\" && depositAmountMode === \"usd\"\n ? parsedAmount\n : destinationAmount.mul(destinationRate);\n const destinationCoverage = getExactOutDestinationBalanceCoverage({\n requestedAmount: destinationAmount,\n requestedUsd: destinationUsd,\n token: toToken,\n });\n const destinationUsdNeedingSources = Decimal.max(\n destinationUsd.minus(destinationCoverage?.usd ?? new Decimal(0)),\n new Decimal(0),\n );\n const cachedSourceUsdRatio = parseFiatNumber(\n baseline?.exactOutSourceUsdPerDestinationUsd,\n );\n const requiredSourceUsd = getPredictiveExactOutSourceTargetUsd(\n destinationUsdNeedingSources,\n cachedSourceUsdRatio,\n );\n const sources = requiredSourceUsd.gt(0)\n ? await buildPredictiveExactOutSources(requiredSourceUsd)\n : [];\n\n if (\n cancelled ||\n runId !== predictiveQuoteRunRef.current ||\n (requiredSourceUsd.gt(0) && sources.length === 0)\n ) {\n setPredictiveQuote((current) =>\n current?.mode === \"exactOut\" ? null : current,\n );\n return;\n }\n\n setPredictiveQuote({\n key,\n mode: \"exactOut\",\n sources,\n toAmount: getPredictiveDisplayAmount(destinationAmount, toToken),\n toUsd: destinationUsd.toDecimalPlaces(6).toFixed(),\n });\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n activeMode,\n amount,\n depositAmountMode,\n destinationBalance,\n fromTokensQuoteKey,\n nexusSDK,\n selectedOpportunityIdentity,\n sourceSelectionRevision,\n swapBalance,\n swapStep,\n swapType,\n toToken?.balance,\n toToken?.balanceInFiat,\n toToken?.chainId,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.symbol,\n ]);\n\n const resolvedDepositSourceTokens = useMemo(() => {\n if (activeMode !== \"deposit\" || !swapBalance) return [];\n const selection = getResolvedDepositSourceSelection();\n return getDepositSourceTokensForIds(selection.selectedSourceIds);\n }, [\n activeMode,\n depositSourceFilter,\n depositQuoteAmountKey,\n depositSourceTargetUsdKey,\n depositUsdDecimal.toFixed(),\n fromTokensQuoteKey,\n selectedOpportunity?.chainId,\n selectedOpportunity?.tokenAddress,\n selectedOpportunity?.tokenSymbol,\n sourceSelectionRevision,\n sourceSelectionTouched,\n swapBalance,\n toToken?.chainId,\n toToken?.contractAddress,\n toToken?.symbol,\n ]);\n const lockedDestinationSourceTokens = useMemo(() => {\n if (\n (activeMode !== \"deposit\" && activeMode !== \"send\") ||\n !toToken?.chainId ||\n !requiredDestinationTokenAmount ||\n requiredDestinationTokenAmount.lte(0)\n ) {\n return [];\n }\n\n const heldDestinationToken = getHeldDestinationTokenOption();\n return heldDestinationToken ? [heldDestinationToken] : [];\n }, [\n activeMode,\n requiredDestinationTokenAmount?.toFixed(),\n swapBalance,\n toToken?.chainId,\n toToken?.chainLogo,\n toToken?.chainName,\n toToken?.contractAddress,\n toToken?.decimals,\n toToken?.logo,\n toToken?.symbol,\n ]);\n\n const setSourcePickerDraftSelection = useCallback(\n (tokens: SwapTokenOption[]) => {\n const nextTokens = tokens.map((token) => ({\n ...token,\n userAmount: \"\",\n }));\n sourcePickerDraftTokensRef.current = nextTokens;\n setSourcePickerDraftTokens(nextTokens);\n },\n [],\n );\n\n const getAutoExactOutSourceTokensForPicker = useCallback(() => {\n const autoIntentTokens = lastAutoIntentSourceTokensRef.current;\n if (autoIntentTokens.length > 0) {\n return autoIntentTokens;\n }\n\n if (activeMode === \"deposit\") {\n const selection = getResolvedDepositSourceSelection({\n filter: \"all\",\n isManualSelection: false,\n });\n const resolvedTokens = getDepositSourceTokensForIds(\n selection.selectedSourceIds,\n );\n if (resolvedTokens.length > 0) {\n return resolvedTokens;\n }\n }\n\n if (activeMode === \"send\") {\n const gasCapable = getGasCapableBalanceSourceTokens();\n if (gasCapable.length > 0) {\n return gasCapable;\n }\n }\n\n return sourceSelectionTouched ? [] : fromTokens;\n }, [\n activeMode,\n fromTokens,\n getDepositSourceTokensForIds,\n getGasCapableBalanceSourceTokens,\n getResolvedDepositSourceSelection,\n sourceSelectionTouched,\n ]);\n\n const resetSourcePickerDraft = useCallback(() => {\n sourcePickerDraftTokensRef.current = null;\n setSourcePickerDraftTokens(null);\n }, []);\n\n const beginSourcePickerEdit = useCallback(() => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") {\n resetSourcePickerDraft();\n return;\n }\n\n sourcePickerDraftDepositFilterRef.current = depositSourceFilter;\n sourcePickerDraftTouchedRef.current = sourceSelectionTouched;\n sourcePickerDraftModeRef.current = exactOutQuoteSourceModeRef.current;\n setSourcePickerDraftSelection(fromTokens);\n }, [\n activeMode,\n depositSourceFilter,\n fromTokens,\n resetSourcePickerDraft,\n setSourcePickerDraftSelection,\n sourceSelectionTouched,\n ]);\n\n const handleSourcePickerCancel = useCallback(() => {\n resetSourcePickerDraft();\n closeDrawerToIdle();\n }, [closeDrawerToIdle, resetSourcePickerDraft]);\n\n const handleSourcePickerDraftSelectionChange = useCallback(\n (tokens: SwapTokenOption[], tab: SourceFilterTab = \"custom\") => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n\n setSourcePickerDraftSelection(tokens);\n sourcePickerDraftTouchedRef.current = true;\n sourcePickerDraftModeRef.current = \"selected\";\n sourcePickerDraftDepositFilterRef.current =\n tab === \"stables\" ? \"stablecoins\" : tab;\n },\n [activeMode, setSourcePickerDraftSelection],\n );\n\n const handleSourcePickerFilterTabSelect = useCallback(\n (tab: SourceFilterTab, scopedTokens?: SwapTokenOption[]) => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n\n const nextFilter: DepositSourceFilter =\n tab === \"stables\" ? \"stablecoins\" : tab;\n\n if (tab === \"custom\") {\n sourcePickerDraftDepositFilterRef.current = \"custom\";\n sourcePickerDraftTouchedRef.current = true;\n sourcePickerDraftModeRef.current = \"selected\";\n return;\n }\n if (scopedTokens) {\n handleSourcePickerDraftSelectionChange(scopedTokens, tab);\n return;\n }\n\n if (tab === \"all\") {\n sourcePickerDraftDepositFilterRef.current = nextFilter;\n sourcePickerDraftTouchedRef.current = false;\n sourcePickerDraftModeRef.current = \"all\";\n setSourcePickerDraftSelection(getAutoExactOutSourceTokensForPicker());\n return;\n }\n\n if (activeMode !== \"deposit\") return;\n\n const selection = getResolvedDepositSourceSelection({\n filter: nextFilter,\n isManualSelection: false,\n });\n const sourcePoolTokens = getDepositSourceTokensForIds(\n selection.sourcePoolIds,\n );\n\n sourcePickerDraftDepositFilterRef.current = nextFilter;\n sourcePickerDraftTouchedRef.current = false;\n sourcePickerDraftModeRef.current = \"all\";\n setSourcePickerDraftSelection(sourcePoolTokens);\n },\n [\n activeMode,\n getAutoExactOutSourceTokensForPicker,\n handleSourcePickerDraftSelectionChange,\n getDepositSourceTokensForIds,\n getResolvedDepositSourceSelection,\n setSourcePickerDraftSelection,\n ],\n );\n\n const commitSourcePickerDraft = useCallback(\n (tokens?: SwapTokenOption[]) => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") {\n resetSourcePickerDraft();\n closeDrawerToIdle();\n return;\n }\n\n const nextTokens =\n tokens ?? sourcePickerDraftTokensRef.current ?? fromTokens;\n const normalizedTokens = nextTokens.map((token) => ({\n ...token,\n userAmount: \"\",\n }));\n\n setSourceSelectionTouched(sourcePickerDraftTouchedRef.current);\n setExactOutQuoteSourceModeValue(sourcePickerDraftModeRef.current);\n setDepositSourceFilter(sourcePickerDraftDepositFilterRef.current);\n invalidateExactOutQuoteForRefresh({\n sourceTokens: normalizedTokens,\n });\n setSourceSelectionRevision((current) => current + 1);\n setFromTokens(normalizedTokens);\n resetSourcePickerDraft();\n closeDrawerToIdle();\n },\n [\n activeMode,\n closeDrawerToIdle,\n fromTokens,\n invalidateExactOutQuoteForRefresh,\n resetSourcePickerDraft,\n setExactOutQuoteSourceModeValue,\n ],\n );\n\n const sourcePickerSelectedTokens =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n swapStep === \"choose-swap-asset\"\n ? (sourcePickerDraftTokens ?? fromTokens)\n : fromTokens;\n\n useEffect(() => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n if (lockedDestinationSourceTokens.length === 0) return;\n if (activeMode === \"deposit\" && !sourceSelectionTouched) return;\n\n setFromTokens((current) => {\n const missing = lockedDestinationSourceTokens.filter(\n (locked) =>\n !current.some(\n (token) =>\n getTokenSelectionKey(token) === getTokenSelectionKey(locked),\n ),\n );\n if (missing.length === 0) return current;\n return [\n ...current,\n ...missing.map((token) => ({ ...token, userAmount: \"\" })),\n ];\n });\n }, [activeMode, lockedDestinationSourceTokens, sourceSelectionTouched]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\") return;\n if (sourceSelectionTouched) return;\n if (\n !toToken ||\n !depositTokenAmountForQuote ||\n depositTokenAmountForQuote.lte(0)\n ) {\n return;\n }\n if (resolvedDepositSourceTokens.length === 0) {\n return;\n }\n\n setFromTokens((current) => {\n const canInitialize = current.length === 0;\n if (!canInitialize) return current;\n\n const next: SwapTokenOption[] = [];\n const seen = new Set();\n for (const token of resolvedDepositSourceTokens) {\n const key = getTokenSelectionKey(token);\n if (!key || seen.has(key)) continue;\n seen.add(key);\n next.push({ ...token, userAmount: \"\" });\n }\n\n const currentKeys = current.map(getTokenSelectionKey).sort().join(\"|\");\n const nextKeys = next.map(getTokenSelectionKey).sort().join(\"|\");\n if (currentKeys === nextKeys) return current;\n return next;\n });\n }, [\n activeMode,\n depositQuoteAmountKey,\n resolvedDepositSourceTokens,\n sourceSelectionTouched,\n toTokenQuoteKey,\n ]);\n\n // ---------------------------------------------------------------------------\n // Handlers\n // ---------------------------------------------------------------------------\n\n const applyConfiguredPrefillsAfterReset = () => {\n const prefillAmount = config.prefill?.amount ?? \"\";\n const prefillRecipient = config.prefill?.recipient ?? \"\";\n\n appliedTokenPrefillRef.current = null;\n syncingIntentSourcesRef.current = false;\n maxPercentRunRef.current += 1;\n setAmount(prefillAmount);\n setRecipientAddress(prefillRecipient);\n setTxError(null);\n setSwapQuoteIssue(null);\n setIntentToAmount(undefined);\n setIntentFeeUsd(undefined);\n setIntentData(null);\n setPredictiveQuote(null);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setPreviewQuoteRefreshing(false);\n setMaxCalculationPercent(null);\n setSourceSelectionTouched(false);\n setDepositSourceFilter(\"all\");\n setExactOutQuoteSourceModeValue(\"all\");\n setSourceSelectionRevision((current) => current + 1);\n setDepositAmountMode(\"token\");\n\n if (activeMode === \"swap\") {\n const sourcePrefill = config.prefill?.source;\n const destinationPrefill = config.prefill?.destination;\n const sourceToken = resolvePrefillToken(sourcePrefill);\n const destinationToken = resolvePrefillToken(destinationPrefill);\n\n setFromTokens(\n sourceToken\n ? [\n {\n ...sourceToken,\n userAmount: prefillAmount,\n },\n ]\n : [],\n );\n setSourceSelectionTouched(Boolean(sourceToken));\n setToToken(destinationToken);\n setSelectedOpportunity(undefined);\n setSwapType(\"exactIn\");\n\n if (\n (!sourcePrefill || sourceToken) &&\n (!destinationPrefill || destinationToken) &&\n (sourcePrefill || destinationPrefill)\n ) {\n appliedTokenPrefillRef.current = [\n sourcePrefill\n ? `source:${sourcePrefill.chain}:${sourcePrefill.token.toLowerCase()}`\n : \"\",\n destinationPrefill\n ? `destination:${destinationPrefill.chain}:${destinationPrefill.token.toLowerCase()}`\n : \"\",\n config.prefill?.amount ? `amount:${config.prefill.amount}` : \"\",\n ].join(\"|\");\n }\n return;\n }\n\n if (activeMode === \"send\") {\n const sendPrefill =\n config.prefill?.token && config.prefill?.chain\n ? {\n token: config.prefill.token,\n chain: config.prefill.chain,\n }\n : config.prefill?.destination;\n const token = resolvePrefillToken(sendPrefill);\n\n setFromTokens([]);\n setSelectedOpportunity(undefined);\n setToToken(token);\n setSwapType(\"exactOut\");\n\n if (sendPrefill && token) {\n appliedTokenPrefillRef.current = `send:${sendPrefill.chain}:${sendPrefill.token.toLowerCase()}`;\n }\n return;\n }\n\n const destinationPrefill = config.prefill?.destination;\n const configuredPrefillDeposit = destinationPrefill\n ? configuredDepositOptions.find(\n (deposit) =>\n deposit.chainId === destinationPrefill.chain &&\n deposit.tokenAddress.toLowerCase() ===\n destinationPrefill.token.toLowerCase(),\n )\n : undefined;\n const nextDeposit = configuredPrefillDeposit ?? configuredDeposit;\n\n setFromTokens([]);\n setSelectedOpportunity(nextDeposit);\n setToToken(nextDeposit ? toTokenFromOpportunity(nextDeposit) : undefined);\n setSwapType(\"exactOut\");\n };\n\n const handleReset = () => {\n clearPendingSwapIntent();\n setSwapStep(\"idle\");\n setCurrentSwapId(null);\n currentSwapIdRef.current = null;\n currentSwapStartedAtRef.current = 0;\n amountEnteredLastValueRef.current = config.prefill?.amount ?? \"\";\n applyConfiguredPrefillsAfterReset();\n rotateAttempt();\n };\n\n const resetSourceSelectionAfterFailure = () => {\n lastAutoIntentSourceTokensRef.current = [];\n lastIntentSourceTokensRef.current = [];\n resetSourcePickerDraft();\n resetExactOutSourcesToAuto();\n };\n\n const handleFailureBack = () => {\n clearPendingSwapIntent();\n resetSourceSelectionAfterFailure();\n setTxError(null);\n void refreshSelectedSourceBalances();\n setSwapStep(\"idle\");\n setCurrentSwapId(null);\n currentSwapIdRef.current = null;\n currentSwapStartedAtRef.current = 0;\n rotateAttempt();\n };\n\n const clearTerminalInputState = () => {\n setAmount(\"\");\n setRecipientAddress(\"\");\n setTxError(null);\n setSwapQuoteIssue(null);\n setIntentToAmount(undefined);\n setIntentFeeUsd(undefined);\n setIntentData(null);\n setFromTokens((current) => (current.length === 0 ? current : []));\n setSourceSelectionTouched(false);\n setDepositSourceFilter(\"all\");\n setDepositAmountMode(\"token\");\n };\n\n const resetInputsAfterSuccessfulExecution = () => {\n clearTerminalInputState();\n if (activeMode === \"deposit\") {\n setSelectedOpportunity(configuredDeposit);\n setToToken(\n configuredDeposit\n ? toTokenFromOpportunity(configuredDeposit)\n : undefined,\n );\n } else {\n setToToken(undefined);\n }\n };\n\n const handleTerminalReceiptDone = () => {\n clearPendingSwapIntent();\n clearTerminalInputState();\n void refreshSelectedSourceBalances();\n setSwapStep(\"idle\");\n setCurrentSwapId(null);\n currentSwapIdRef.current = null;\n currentSwapStartedAtRef.current = 0;\n amountEnteredLastValueRef.current = \"\";\n rotateAttempt();\n };\n\n const handleModalOpenChange = useCallback(\n (open: boolean) => {\n if (!open && swapStepRef.current === \"progress\") return;\n if (!isControlledOpen) {\n setInternalOpen(open);\n }\n onOpenChange?.(open);\n if (!open) {\n clearPendingSwapIntent();\n onClose?.();\n }\n },\n [clearPendingSwapIntent, isControlledOpen, onClose, onOpenChange],\n );\n\n const handleClose = () => {\n if (!embed) {\n handleModalOpenChange(false);\n return;\n }\n clearPendingSwapIntent();\n onClose?.();\n };\n\n const handleConnectWallet = async () => {\n if (walletActionPending || nexusLoading) return;\n\n const clickHandler = onConnectClick || onConnectWallet;\n if (clickHandler) {\n setWalletActionPending(true);\n setTxError(null);\n try {\n await clickHandler();\n } catch (error: any) {\n setTxError(error?.message || \"Unable to connect wallet.\");\n } finally {\n setWalletActionPending(false);\n }\n return;\n }\n\n if (isWalletConnectPending) return;\n\n setWalletActionPending(true);\n setTxError(null);\n try {\n let activeConnector = connector;\n\n if (walletStatus !== \"connected\") {\n const nextConnector = connectors[0];\n if (!nextConnector) {\n throw new Error(\"No wallet connector available.\");\n }\n await connectAsync({ connector: nextConnector });\n return;\n }\n\n const effectiveProvider =\n await getEffectiveWalletProvider(activeConnector);\n\n if (\n !effectiveProvider ||\n typeof effectiveProvider.request !== \"function\"\n ) {\n throw new Error(\"Wallet provider is not ready yet.\");\n }\n\n await handleInit(effectiveProvider as EthereumProvider, ownerAddress);\n } catch (error: any) {\n setTxError(error?.message || \"Unable to connect wallet.\");\n } finally {\n setWalletActionPending(false);\n }\n };\n\n const handleConnectOnrampWallet = async () => {\n const controller = new AbortController();\n const liveAddress = await withOnrampWalletTimeout(async () => {\n const provider = await getOnrampWalletProvider();\n return provider ? readOnrampWalletAddress(provider) : undefined;\n }, controller.signal).catch(() => undefined);\n if (!liveAddress && connector && walletStatus === \"connected\") {\n // Clear a persisted, unusable connector before opening Reown's connection UI.\n await disconnectAsync({ connector });\n }\n const clickHandler = onConnectClick || onConnectWallet;\n if (clickHandler) {\n await clickHandler();\n } else if (!liveAddress) {\n const nextConnector = connector ?? connectors[0];\n if (!nextConnector) throw new Error(\"No wallet connector available.\");\n await connectAsync({ connector: nextConnector });\n } else {\n const provider = await getOnrampWalletProvider();\n if (provider) await handleInit(provider, liveAddress);\n }\n };\n\n const handleOpenRecipientEditor = () => {\n if (activeMode === \"swap\" && !recipientAddress && defaultRecipientAddress) {\n setRecipientAddress(defaultRecipientAddress);\n }\n setTxError(null);\n openDrawerStep(\"enter-recipient\");\n };\n\n const handleResetRecipientToDefault = () => {\n setRecipientAddress(defaultRecipientAddress);\n setTxError(null);\n };\n\n const handleSaveRecipient = () => {\n const next = recipientAddress.trim();\n if (!next) {\n setTxError(\"Recipient address is required\");\n return;\n }\n if (!next.endsWith(\".eth\") && !isAddress(next)) {\n setTxError(\"Incorrect address\");\n return;\n }\n if (\n activeMode === \"send\" &&\n ownerAddress &&\n isAddress(next) &&\n next.toLowerCase() === ownerAddress.toLowerCase()\n ) {\n setTxError(\"Recipient cannot be the connected wallet.\");\n return;\n }\n setRecipientAddress(next);\n setTxError(null);\n closeDrawerToIdle();\n };\n\n /** Start swap flow — v2 SDK per-operation onIntent hooks populate preview. */\n const handleEnterPreview = async (options: { background?: boolean } = {}) => {\n const { background = false } = options;\n const isExactOutFlow = activeMode === \"deposit\" || activeMode === \"send\";\n const quoteInputKey = activeQuoteInputKeyRef.current;\n const isCurrentQuoteInput = () =>\n activeQuoteInputKeyRef.current === quoteInputKey;\n\n if (!toToken) {\n return;\n }\n\n if (isExactOutFlow) {\n if (!hasPositiveDecimalInput(amount)) {\n return;\n }\n } else if (!hasReadyExactInSwapInput(fromTokens, toToken)) {\n if (!background) {\n setTxError(null);\n setSwapQuoteIssue(null);\n }\n return;\n }\n\n const receiveIssue = buildReceiveAmountIssue();\n if (receiveIssue) {\n applyReceiveAmountIssue(receiveIssue);\n if (!background && swapStepRef.current !== \"idle\") {\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n }\n return;\n }\n\n const configuredIssue = buildConfiguredAmountIssue();\n if (configuredIssue) {\n clearPreviewForBlockingAmountIssue();\n if (!background && swapStepRef.current !== \"idle\") {\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n }\n return;\n }\n\n const sourceBalanceIssue = isExactOutFlow\n ? buildExactOutSourceBalanceIssue()\n : null;\n if (sourceBalanceIssue) {\n clearPreviewForBlockingAmountIssue();\n setSwapQuoteIssue(sourceBalanceIssue);\n if (!background && swapStepRef.current !== \"idle\") {\n swapStepRef.current = \"idle\";\n setSwapStep(\"idle\");\n }\n return;\n }\n\n if (!background && activeMode === \"deposit\") {\n trackDeposit(\"deposit_confirm_clicked\", {\n amountToken: depositTokenDisplay,\n amountUsd: Number(depositUsdDisplay) || 0,\n selectionMode: sourceSelectionTouched ? \"manual\" : \"auto\",\n sourceCount: (intentData?.sources ?? []).length,\n });\n }\n\n setTxError(null);\n setSwapQuoteIssue(null);\n\n if (\n !background &&\n swapIntentRef.current?.runId === swapRunIdRef.current &&\n swapIntentRef.current?.quoteInputKey === quoteInputKey &&\n intentData &&\n (activeMode !== \"send\" || Boolean(recipientAddress)) &&\n ((activeMode !== \"deposit\" && activeMode !== \"send\") ||\n (intentData.sources ?? []).length > 0 ||\n Boolean(intentData.destination))\n ) {\n swapStepRef.current = \"preview-intent\";\n setSwapStep(\"preview-intent\");\n return;\n }\n\n let resolvedRecipientAddress =\n activeMode === \"swap\" ? effectiveRecipientAddress : recipientAddress;\n\n if (!background && activeMode === \"send\" && !resolvedRecipientAddress) {\n setTxError(\"Recipient address is required\");\n return;\n }\n\n if ((!background && activeMode === \"send\") || hasCustomSwapRecipient) {\n if (!resolvedRecipientAddress) {\n setTxError(\"Recipient address is required\");\n return;\n }\n\n if (\n activeMode === \"send\" &&\n ownerAddress &&\n isAddress(resolvedRecipientAddress) &&\n resolvedRecipientAddress.toLowerCase() === ownerAddress.toLowerCase()\n ) {\n setTxError(\"Recipient cannot be the connected wallet.\");\n return;\n }\n\n if (resolvedRecipientAddress.endsWith(\".eth\")) {\n try {\n const mainnetClient =\n publicClient?.chain?.id === 1\n ? publicClient\n : createPublicClient({\n chain: mainnet,\n transport: http(),\n });\n const ensAddr = await mainnetClient.getEnsAddress({\n name: normalize(resolvedRecipientAddress),\n });\n if (!ensAddr) {\n setTxError(\"Could not resolve ENS name to an address.\");\n return;\n }\n resolvedRecipientAddress = ensAddr;\n } catch (e: any) {\n setTxError(e.message || \"Failed to resolve ENS name.\");\n return;\n }\n } else {\n if (!isAddress(resolvedRecipientAddress)) {\n setTxError(\"Invalid recipient address.\");\n return;\n }\n }\n\n if (\n activeMode === \"send\" &&\n ownerAddress &&\n isAddress(resolvedRecipientAddress) &&\n resolvedRecipientAddress.toLowerCase() === ownerAddress.toLowerCase()\n ) {\n setTxError(\"Recipient cannot be the connected wallet.\");\n return;\n }\n }\n\n if (!isCurrentQuoteInput()) {\n return;\n }\n\n if (!background) {\n swapStepRef.current = \"preview-intent\";\n setSwapStep(\"preview-intent\");\n }\n setIntentLoading(true);\n setQuoteRefreshing(background);\n setIntentToAmount(undefined);\n setIntentFeeUsd(undefined);\n setIntentData(null);\n swapIntentRef.current?.deny();\n swapIntentRef.current = null;\n if (!background) {\n resetProgressEvents();\n swapStepsListRef.current = [];\n resetSteps();\n }\n\n if (!nexusSDK) {\n setTxError(\"SDK not initialized\");\n if (!background) {\n setSwapStep(\"idle\");\n }\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n swapRunIdRef.current += 1;\n const runId = swapRunIdRef.current;\n\n const isActionPlanStep = (step: SwapStepType | BridgeStepType) => {\n const type = getProgressStepType(step);\n return (\n type === \"APPROVAL\" ||\n type === \"TRANSACTION_SENT\" ||\n type === \"TRANSACTION_CONFIRMED\"\n );\n };\n\n const hasSwapPlanSteps = (stepList: Array) =>\n stepList.some((step) => !isActionPlanStep(step));\n\n const handleProgressStepSideEffects = (\n event: any,\n step: SwapStepType | BridgeStepType,\n completed: boolean,\n ) => {\n const type = getProgressStepType(step);\n const rawStepType = String(\n event?.stepType ?? (step as any)?.type ?? (step as any)?.typeID ?? \"\",\n ).toLowerCase();\n const rawState = String(event?.state ?? \"\").toLowerCase();\n const explorerUrl = getPlanStepExplorerUrl(event, step);\n const sourceMovementStep = isSourceMovementProgressStep(\n type,\n rawStepType,\n );\n const hasSourceMovementTransaction = Boolean(\n explorerUrl || getPlanStepTransactionHash(event, step),\n );\n const intentExplorerUrl = getEventIntentExplorerUrl(\n appConfig.nexusNetwork,\n event,\n step,\n );\n\n patchCurrentIntentExplorerUrl(intentExplorerUrl);\n\n if (\n type === \"TRANSACTION_SENT\" ||\n type === \"TRANSACTION_CONFIRMED\" ||\n type === \"SOURCE_SWAP\" ||\n type === \"BRIDGE_DEPOSIT\" ||\n type === \"BRIDGE_INTENT_SUBMISSION\" ||\n type === \"BRIDGE_FILL\" ||\n type === \"DESTINATION_SWAP\" ||\n type === \"SWAP_COMPLETE\" ||\n type === \"SWAP_SKIPPED\"\n ) {\n markSwapExecutionStarted();\n }\n\n if (\n sourceMovementStep &&\n hasSourceMovementTransaction &&\n PLAN_STEP_FUNDS_MAY_HAVE_MOVED_STATES.has(rawState)\n ) {\n fundsMovedRef.current = true;\n }\n\n if (explorerUrl) {\n if (\n rawStepType === \"destination_swap\" ||\n rawStepType === \"execute_transaction\" ||\n type.includes(\"DESTINATION_SWAP\") ||\n type === \"TRANSACTION_SENT\" ||\n type === \"TRANSACTION_CONFIRMED\"\n ) {\n mergeExplorerUrls({ destinationExplorerUrl: explorerUrl });\n } else if (sourceMovementStep) {\n mergeExplorerUrls({ sourceExplorerUrl: explorerUrl });\n }\n\n if (\n !intentUrlRef.current &&\n (rawStepType === \"bridge_intent_submission\" ||\n rawStepType === \"request_submission\" ||\n type === \"BRIDGE_INTENT_SUBMISSION\")\n ) {\n patchCurrentIntentExplorerUrl(explorerUrl);\n }\n }\n\n if (completed) {\n onStepComplete(step as SwapStepType);\n }\n };\n\n const handlePlanEvent = (event: any) => {\n if (event.type === \"plan_preview\" || event.type === \"plan_confirmed\") {\n const stepList = Array.isArray(event.plan?.steps)\n ? event.plan.steps.map((step: any) =>\n normalizePlanStep(step, step?.type, undefined, false),\n )\n : [];\n logSwapPlanSteps(event.type, stepList, event.plan?.steps);\n if (stepList.length === 0) return;\n\n if (hasSwapPlanSteps(stepList)) {\n swapStepsListRef.current = stepList as SwapStepType[];\n appendProgressListEvent(\n PROGRESS_EVENT_NAMES.SWAP_PLAN_LIST,\n stepList,\n );\n } else {\n appendProgressListEvent(\n PROGRESS_EVENT_NAMES.BRIDGE_PLAN_LIST,\n stepList,\n );\n }\n onStepsList(stepList as SwapStepType[]);\n return;\n }\n\n if (event.type !== \"plan_progress\") {\n logSdkSwapEvent(\"unhandled typed event\", event);\n return;\n }\n\n const state = String(event.state ?? \"\").toLowerCase();\n const completed = PLAN_FINAL_STATES.has(state);\n const step = normalizePlanStep(\n event.step,\n event.stepType,\n event.state,\n completed,\n );\n const eventName = isActionPlanStep(step)\n ? PROGRESS_EVENT_NAMES.BRIDGE_PLAN_PROGRESS\n : PROGRESS_EVENT_NAMES.SWAP_PLAN_PROGRESS;\n\n logSwapPlanProgress(event, step, eventName, completed);\n appendProgressEvent(eventName, step, completed, event);\n handleProgressStepSideEffects(event, step, completed);\n };\n\n const appendSkippedSwapProgress = () => {\n const step = {\n completed: true,\n type: \"SWAP_SKIPPED\",\n typeID: \"SWAP_SKIPPED\",\n } as SwapStepType;\n enterSkippedSwapProgress();\n appendProgressEvent(PROGRESS_EVENT_NAMES.SWAP_PLAN_PROGRESS, step, true);\n onStepComplete(step);\n };\n\n const handleSwapEvent = (event: any) => {\n if (!event || typeof event !== \"object\") return;\n if (typeof event.type === \"string\") {\n handlePlanEvent(event);\n return;\n }\n logSdkSwapEvent(\"ignored event without string type\", event);\n };\n\n const onEvent = (event: any) => {\n const isCurrentRun = swapRunIdRef.current === runId;\n const isCurrentQuote = isCurrentQuoteInput();\n logSdkSwapEvent(\"onEvent\", event, {\n currentRunId: swapRunIdRef.current,\n isCurrentQuote,\n isCurrentRun,\n quoteInputKey,\n runId,\n });\n if (!isCurrentRun || !isCurrentQuote) {\n logSdkSwapEvent(\"ignored stale onEvent\", event, {\n currentRunId: swapRunIdRef.current,\n isCurrentQuote,\n quoteInputKey,\n runId,\n });\n return;\n }\n patchCurrentIntentExplorerUrl(\n getEventIntentExplorerUrl(appConfig.nexusNetwork, event),\n );\n handleSwapEvent(event);\n };\n\n const buildRecipientTransferExecuteConfig = (transferAmount: bigint) => {\n if (!resolvedRecipientAddress) {\n throw new Error(\"Recipient address is required\");\n }\n\n const isNative =\n !toToken.contractAddress ||\n toToken.contractAddress.toLowerCase() ===\n \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\" ||\n toToken.contractAddress ===\n \"0x0000000000000000000000000000000000000000\";\n\n if (isNative) {\n return {\n to: resolvedRecipientAddress as `0x${string}`,\n value: transferAmount,\n gas: BigInt(100000),\n };\n }\n\n return {\n to: toToken.contractAddress as `0x${string}`,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"transfer\",\n args: [resolvedRecipientAddress as `0x${string}`, transferAmount],\n }),\n gas: BigInt(100000),\n };\n };\n\n const executeRecipientTransfer = async (transferAmount: bigint) => {\n const result = await nexusSDK.execute(\n {\n toChainId: toToken.chainId!,\n ...buildRecipientTransferExecuteConfig(transferAmount),\n },\n { onEvent },\n );\n const finalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n getSdkTransactionHash(result),\n result,\n );\n if (finalExplorerUrl) {\n setTransferExplorerUrl(finalExplorerUrl);\n mergeExplorerUrls({ destinationExplorerUrl: finalExplorerUrl });\n }\n return finalExplorerUrl;\n };\n\n try {\n if (!isExactOutFlow) {\n const fromPayload: {\n chainId: number;\n tokenAddress: `0x${string}`;\n amountRaw: bigint;\n }[] = [];\n\n const exactInSourceTokens = getReadyExactInSourceTokens(fromTokens);\n\n for (const token of exactInSourceTokens) {\n // Determine the amount to use for this specific token\n let rawAmountStr = token.userAmount;\n if (!rawAmountStr && exactInSourceTokens.length === 1) {\n rawAmountStr = amount; // fallback for single-token case\n }\n\n let cleanAmount = parseFiatNumber(rawAmountStr) ?? new Decimal(0);\n if (cleanAmount.lte(0)) continue;\n\n if (token.userAmountMode === \"usd\") {\n const tokenBalance =\n parseFiatNumber(token.balance) ?? new Decimal(0);\n const fiatBalance =\n parseFiatNumber(token.balanceInFiat) ?? new Decimal(0);\n const price = tokenBalance.gt(0)\n ? fiatBalance.div(tokenBalance)\n : new Decimal(0);\n if (price.gt(0)) {\n cleanAmount = cleanAmount.div(price);\n } else {\n cleanAmount = new Decimal(0);\n }\n }\n\n if (cleanAmount.lte(0)) continue;\n\n const safeTokenAmountStr = toViemDecimalString(\n cleanAmount,\n token.decimals || 18,\n );\n\n fromPayload.push({\n chainId: token.chainId!,\n tokenAddress: token.contractAddress as `0x${string}`,\n amountRaw: parseUnits(safeTokenAmountStr, token.decimals || 18),\n });\n }\n\n if (fromPayload.length === 0) {\n throw new Error(\"No source amount available for swap.\");\n }\n\n resetExplorerUrls();\n const exactInSwapPayload = {\n sources: fromPayload,\n toChainId: toToken.chainId!,\n toTokenAddress: toToken.contractAddress as `0x${string}`,\n };\n let intentExplorerUrl: string | null = null;\n let intentId = currentSwapEntry?.intentId;\n let finalExplorerUrl: string | null =\n explorerUrlsRef.current.destinationExplorerUrl ||\n explorerUrlsRef.current.sourceExplorerUrl;\n\n if (hasCustomSwapRecipient && resolvedRecipientAddress) {\n const sdkWithOptionalTransfer = nexusSDK as any;\n\n if (typeof sdkWithOptionalTransfer.swapAndTransfer === \"function\") {\n const swapAndTransferExactInInput = {\n mode: \"exactIn\",\n recipient: resolvedRecipientAddress as `0x${string}`,\n ...exactInSwapPayload,\n };\n logSdkIntentInput(\n \"swapAndTransfer exactIn\",\n swapAndTransferExactInInput,\n {\n activeMode,\n quoteInputKey,\n runId,\n },\n );\n const result = await sdkWithOptionalTransfer.swapAndTransfer(\n swapAndTransferExactInInput,\n { onEvent },\n );\n if (result?.success === false) {\n throw new Error(result?.error || \"Swap and transfer failed\");\n }\n\n const swapResult = getSdkSwapResult(result);\n intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result,\n swapResult,\n );\n intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n const resultFinalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n getSdkTransactionHash(result),\n result,\n swapResult,\n );\n finalExplorerUrl = resultFinalExplorerUrl || finalExplorerUrl;\n if (resultFinalExplorerUrl) {\n setTransferExplorerUrl(resultFinalExplorerUrl);\n mergeExplorerUrls({\n destinationExplorerUrl: resultFinalExplorerUrl,\n });\n }\n } else {\n logSdkIntentInput(\"swapWithExactIn\", exactInSwapPayload, {\n activeMode,\n quoteInputKey,\n runId,\n });\n startIntentFetchTiming({\n background,\n operation: \"swapWithExactIn\",\n quoteInputKey,\n runId,\n });\n const result = await nexusSDK.swapWithExactIn(exactInSwapPayload, {\n hooks: {\n onIntent: (data) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n },\n onEvent,\n });\n\n intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result,\n );\n intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n\n const latestSwapIntent = (\n swapIntentRef.current as unknown as {\n intent?: SwapIntentData;\n } | null\n )?.intent;\n const transferAmount = latestSwapIntent?.destination?.amount;\n if (!transferAmount) {\n throw new Error(\n \"Unable to determine received amount to transfer.\",\n );\n }\n\n const transferAmountBigInt = parseUnits(\n toViemDecimalString(transferAmount, toToken.decimals || 18),\n toToken.decimals || 18,\n );\n finalExplorerUrl =\n (await executeRecipientTransfer(transferAmountBigInt)) ||\n finalExplorerUrl;\n }\n } else {\n // Start exact-in swap — the intent hook will fire and populate preview\n logSdkIntentInput(\"swapWithExactIn\", exactInSwapPayload, {\n activeMode,\n quoteInputKey,\n runId,\n });\n startIntentFetchTiming({\n background,\n operation: \"swapWithExactIn\",\n quoteInputKey,\n runId,\n });\n const result = await nexusSDK.swapWithExactIn(exactInSwapPayload, {\n hooks: {\n onIntent: (data) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n },\n onEvent,\n });\n intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result,\n );\n intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n const swapResult = getSdkSwapResult(result);\n const resultFinalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n getSdkTransactionHash(result),\n result,\n swapResult,\n );\n finalExplorerUrl = resultFinalExplorerUrl || finalExplorerUrl;\n if (resultFinalExplorerUrl) {\n setTransferExplorerUrl(resultFinalExplorerUrl);\n mergeExplorerUrls({\n destinationExplorerUrl: resultFinalExplorerUrl,\n });\n }\n }\n\n if (\n swapRunIdRef.current === runId &&\n swapStepRef.current === \"progress\"\n ) {\n const resolvedFinalExplorerUrl =\n finalExplorerUrl ||\n explorerUrlsRef.current.destinationExplorerUrl ||\n explorerUrlsRef.current.sourceExplorerUrl;\n const resolvedIntentExplorerUrl =\n intentExplorerUrl || intentUrlRef.current;\n finishCurrentSwapHistoryEntry(\"fulfilled\", {\n finalExplorerUrl: resolvedFinalExplorerUrl,\n ...(resolvedIntentExplorerUrl\n ? { intentExplorerUrl: resolvedIntentExplorerUrl }\n : {}),\n ...(intentId ? { intentId } : {}),\n });\n resetInputsAfterSuccessfulExecution();\n onComplete?.();\n setSwapStep(\"success\");\n }\n } else {\n const exactOutAmountString =\n activeMode === \"deposit\"\n ? depositTokenAmountForQuote\n ?.toDecimalPlaces(toToken.decimals || 18, Decimal.ROUND_DOWN)\n .toFixed()\n : amount;\n if (!exactOutAmountString || new Decimal(exactOutAmountString).lte(0)) {\n setTxError(\n depositAmountMode === \"usd\"\n ? \"Unable to convert USD amount into the destination token amount.\"\n : \"Enter a valid amount.\",\n );\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n const amountBigInt = parseUnits(\n toViemDecimalString(exactOutAmountString, toToken.decimals || 18),\n toToken.decimals || 18,\n );\n\n resetExplorerUrls();\n\n const fromSourcesPayload = buildExactOutSourcesPayload(\n getExactOutSourceTokens(),\n );\n\n let executeConfig: any;\n if (activeMode === \"deposit\" && !selectedOpportunity?.executeDeposit) {\n throw new Error(\"Deposit config is missing executeDeposit.\");\n }\n\n if (activeMode === \"deposit\" && selectedOpportunity) {\n const user = (ownerAddress ?? connectedAddress) as `0x${string}`;\n\n const executeParams = selectedOpportunity.executeDeposit(\n selectedOpportunity.tokenSymbol,\n selectedOpportunity.tokenAddress,\n amountBigInt,\n selectedOpportunity.chainId,\n user,\n );\n if (!isPositiveGasLimit(executeParams.gas)) {\n throw new Error(\n \"Deposit config executeDeposit must return a positive gas limit.\",\n );\n }\n executeConfig = {\n to: executeParams.to,\n value: executeParams.value,\n data: executeParams.data,\n tokenApproval: executeParams.tokenApproval,\n gas: executeParams.gas,\n };\n } else if (\n (activeMode === \"send\" || hasCustomSwapRecipient) &&\n resolvedRecipientAddress\n ) {\n executeConfig = buildRecipientTransferExecuteConfig(amountBigInt);\n }\n\n if (executeConfig?.tokenApproval) {\n executeConfig = {\n ...executeConfig,\n tokenApproval: {\n toTokenAddress:\n executeConfig.tokenApproval.toTokenAddress ||\n toToken.contractAddress,\n amount: executeConfig.tokenApproval.amount,\n spender: executeConfig.tokenApproval.spender,\n },\n };\n }\n\n if (executeConfig) {\n const sdkWithOptionalTransfer = nexusSDK as any;\n const isTransferExactOut =\n (activeMode === \"send\" || hasCustomSwapRecipient) &&\n typeof sdkWithOptionalTransfer.swapAndTransfer === \"function\";\n const exactOutOperationInput = isTransferExactOut\n ? {\n mode: \"exactOut\",\n toChainId: toToken.chainId!,\n toTokenAddress: toToken.contractAddress as `0x${string}`,\n toAmountRaw: amountBigInt,\n recipient: resolvedRecipientAddress as `0x${string}`,\n ...fromSourcesPayload,\n }\n : {\n toChainId: toToken.chainId!,\n toTokenAddress: toToken.contractAddress as `0x${string}`,\n toAmountRaw: amountBigInt,\n execute: executeConfig,\n ...fromSourcesPayload,\n };\n logSdkIntentInput(\n isTransferExactOut\n ? \"swapAndTransfer exactOut\"\n : \"swapAndExecute exactOut\",\n exactOutOperationInput,\n {\n activeMode,\n quoteInputKey,\n runId,\n },\n );\n startIntentFetchTiming({\n background,\n operation: isTransferExactOut\n ? \"swapAndTransfer exactOut\"\n : \"swapAndExecute exactOut\",\n quoteInputKey,\n runId,\n });\n const result = isTransferExactOut\n ? await sdkWithOptionalTransfer.swapAndTransfer(\n exactOutOperationInput,\n {\n onEvent,\n onIntent: (data: any) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n },\n )\n : await nexusSDK.swapAndExecute(exactOutOperationInput as any, {\n onEvent,\n onIntent: (data) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n });\n const swapResult = result?.swapResult ?? result?.result ?? null;\n const swapSkipped = Boolean((result as any)?.swapSkipped);\n if (swapSkipped) {\n appendSkippedSwapProgress();\n }\n if (\n !swapResult &&\n !swapSkipped &&\n activeMode !== \"send\" &&\n !hasCustomSwapRecipient\n ) {\n throw new Error(\"Swap failed\");\n }\n const executeTxHash = getSdkTransactionHash(result);\n const intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result,\n swapResult,\n );\n const intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n const finalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n executeTxHash,\n result,\n swapResult,\n );\n if (finalExplorerUrl) {\n if (activeMode === \"send\" || hasCustomSwapRecipient) {\n setTransferExplorerUrl(finalExplorerUrl);\n }\n mergeExplorerUrls({ destinationExplorerUrl: finalExplorerUrl });\n }\n patchCurrentSwapHistoryEntry({\n ...(finalExplorerUrl ? { finalExplorerUrl } : {}),\n ...(intentExplorerUrl ? { intentExplorerUrl } : {}),\n ...(intentId ? { intentId } : {}),\n });\n } else {\n const exactOutSwapInput = {\n toChainId: toToken.chainId!,\n toTokenAddress: toToken.contractAddress as `0x${string}`,\n toAmountRaw: amountBigInt,\n ...fromSourcesPayload,\n };\n logSdkIntentInput(\"swapWithExactOut\", exactOutSwapInput, {\n activeMode,\n quoteInputKey,\n runId,\n });\n startIntentFetchTiming({\n background,\n operation: \"swapWithExactOut\",\n quoteInputKey,\n runId,\n });\n const result = await nexusSDK.swapWithExactOut(exactOutSwapInput, {\n hooks: {\n onIntent: (data) =>\n handleSwapIntentCallback(data, runId, quoteInputKey),\n },\n onEvent,\n });\n const intentExplorerUrl = getSdkIntentExplorerUrlForNetwork(\n appConfig.nexusNetwork,\n result,\n );\n const intentId =\n extractIntentIdFromUrl(intentExplorerUrl) ??\n currentSwapEntry?.intentId;\n const swapResult = getSdkSwapResult(result);\n const finalExplorerUrl =\n getSdkExplorerUrl(result) ||\n getExplorerTxUrl(\n toToken.chainId,\n getSdkTransactionHash(result),\n result,\n swapResult,\n );\n if (finalExplorerUrl) {\n mergeExplorerUrls({ destinationExplorerUrl: finalExplorerUrl });\n }\n patchCurrentSwapHistoryEntry({\n ...(finalExplorerUrl ? { finalExplorerUrl } : {}),\n ...(intentExplorerUrl ? { intentExplorerUrl } : {}),\n ...(intentId ? { intentId } : {}),\n });\n }\n\n if (\n swapRunIdRef.current === runId &&\n swapStepRef.current === \"progress\"\n ) {\n finishCurrentSwapHistoryEntry(\"fulfilled\");\n resetInputsAfterSuccessfulExecution();\n onComplete?.();\n if (activeMode === \"deposit\") {\n reachedTerminalRef.current = true;\n const now = Date.now();\n trackDeposit(\"deposit_completed\", {\n postConfirmDurationMs: previewConfirmedTsRef.current\n ? now - previewConfirmedTsRef.current\n : 0,\n totalDurationMs: now - widgetOpenedTsRef.current,\n attemptCount: attemptCountRef.current,\n amountToken: depositTokenDisplay,\n amountUsd: Number(depositUsdDisplay) || 0,\n });\n }\n setSwapStep(\"success\");\n }\n }\n } catch (err: any) {\n const caughtTimeout = isTimeoutLikeError(err);\n if (caughtTimeout) {\n console.warn(\"Timeout in handleEnterPreview:\", err);\n } else {\n console.error(\"Error in handleEnterPreview:\", err);\n }\n if (swapRunIdRef.current !== runId || !isCurrentQuoteInput()) {\n return;\n }\n finishIntentFetchTiming(runId, \"failed\");\n if (activeMode === \"deposit\" && err?.code !== \"USER_DENIED_INTENT\") {\n const hasActiveExecution =\n swapStepRef.current === \"progress\" &&\n Boolean(currentSwapIdRef.current);\n const isInsufficient = isInsufficientSourcesError(err);\n const errMessage =\n (typeof err?.message === \"string\" ? err.message : \"\") ||\n (typeof err === \"string\" ? err : \"\");\n const errName = typeof err?.name === \"string\" ? err.name : \"\";\n const isTimeout = isTimeoutLikeError(err);\n const isUserRejected =\n err?.code === 4001 ||\n err?.code === \"ACTION_REJECTED\" ||\n errName === \"UserRejectedRequestError\" ||\n /user rejected|user denied/i.test(errMessage);\n const failedAtStep:\n | \"simulation\"\n | \"nexus_operation\"\n | \"execute_leg\"\n | \"unknown\" = !hasActiveExecution ? \"simulation\" : \"nexus_operation\";\n const errorCategory: string = isUserRejected\n ? \"user_rejected\"\n : isTimeout\n ? \"timeout\"\n : isInsufficient\n ? \"no_eligible_sources\"\n : !hasActiveExecution\n ? \"quote_failed\"\n : fundsMovedRef.current\n ? \"pending_after_funds_moved\"\n : \"execution_failed\";\n reachedTerminalRef.current = true;\n if (fundsMovedRef.current) {\n trackDeposit(\"deposit_pending_after_funds_moved\", {\n errorCode: err?.code ?? \"UNKNOWN\",\n errorMessage: errMessage || \"Transaction pending.\",\n intentUrl: intentUrlRef.current,\n failedAtStep,\n });\n } else {\n trackDeposit(\"deposit_failed\", {\n errorCode: err?.code ?? \"UNKNOWN\",\n errorCategory,\n errorMessage: errMessage || \"Transaction failed.\",\n failedAtStep,\n });\n }\n }\n setQuoteRefreshing(false);\n setIntentLoading(false);\n setReceiveMaxCalculating(false);\n const hasActiveExecution =\n swapStepRef.current === \"progress\" && Boolean(currentSwapIdRef.current);\n const isTimeout = caughtTimeout;\n const showFailedProgressThenReceipt = (\n error: string,\n patch: Partial = {},\n ) => {\n const failedProgressEvent = progressEventsRef.current.at(-1);\n const isTransferExecution =\n activeMode === \"send\" || hasCustomSwapRecipient;\n const fallbackFailedStep =\n activeMode === \"deposit\" || isTransferExecution\n ? ({ type: \"APPROVAL\", typeID: \"AP\" } as BridgeStepType)\n : ({\n type: \"DETERMINING_SWAP\",\n typeID: \"DETERMINING_SWAP\",\n } as unknown as SwapStepType);\n const failedStep = failedProgressEvent?.step ?? fallbackFailedStep;\n const autoRefundAvailable =\n isAutoRefundAvailableProgressEvent(failedProgressEvent);\n setFailedProgressStep(failedStep);\n finishCurrentSwapHistoryEntry(\"failed\", {\n error,\n autoRefundAvailable,\n failureDescription: getFailureDescriptionForProgressStep(\n failedStep,\n autoRefundAvailable,\n ),\n failureMessage: getFailureMessageForProgressStep(\n failedStep,\n hasCustomSwapRecipient ? \"send\" : activeMode,\n autoRefundAvailable,\n ),\n failedStepType: getProgressStepType(failedStep),\n ...patch,\n });\n window.setTimeout(() => {\n if (\n swapRunIdRef.current === runId &&\n swapStepRef.current === \"progress\"\n ) {\n setSwapStep(\"failed\");\n }\n }, 700);\n };\n const showTimeoutReceipt = (\n message = \"Transaction timed out\",\n patch: Partial = {},\n ) => {\n finishCurrentSwapHistoryEntry(\"timeout\", {\n error: message,\n failureDescription:\n \"This transaction is still pending. Check the intent explorer for the latest status.\",\n failureMessage: TIMEOUT_LABEL,\n ...patch,\n });\n window.setTimeout(() => {\n if (\n swapRunIdRef.current === runId &&\n swapStepRef.current === \"progress\"\n ) {\n setSwapStep(\"failed\");\n }\n }, 700);\n };\n if (err?.code === \"USER_DENIED_INTENT\") {\n if (hasActiveExecution) {\n showFailedProgressThenReceipt(\"Transaction cancelled by user\");\n } else if (!background && swapStepRef.current === \"preview-intent\") {\n setSwapStep(\"idle\");\n }\n return;\n }\n if (isInsufficientSourcesError(err) && !hasActiveExecution) {\n const issue = buildInsufficientSourcesIssue(err);\n if (!background || swapStepRef.current === \"preview-intent\") {\n setSwapStep(\"idle\");\n }\n setTxError(null);\n setSwapQuoteIssue(issue);\n onError?.(issue.message);\n return;\n }\n if (\n isExactOutFlow &&\n isViemInvalidDecimalError(err) &&\n !hasActiveExecution\n ) {\n const issue = buildExactOutSourceBalanceIssue();\n if (issue) {\n if (!background || swapStepRef.current === \"preview-intent\") {\n setSwapStep(\"idle\");\n }\n setTxError(null);\n setSwapQuoteIssue(issue);\n onError?.(issue.message);\n return;\n }\n }\n const errorMessage =\n err?.message ||\n (typeof err === \"string\"\n ? err\n : \"Transaction failed. Please try again or check console.\");\n if (isTimeout && hasActiveExecution) {\n showTimeoutReceipt(errorMessage);\n setTxError(null);\n return;\n }\n if (hasActiveExecution && fundsMovedRef.current) {\n showTimeoutReceipt(errorMessage, {\n failureDescription:\n \"Funds have already moved and the transaction is still pending. Check the intent explorer for the latest status.\",\n });\n setTxError(null);\n return;\n }\n if (hasActiveExecution) {\n showFailedProgressThenReceipt(errorMessage);\n } else if (!background || swapStepRef.current === \"preview-intent\") {\n setSwapStep(\"idle\");\n }\n setTxError(errorMessage);\n onError?.(errorMessage);\n }\n };\n\n const hasInsufficientSourcesQuoteIssue =\n swapQuoteIssue?.type === \"insufficientSources\";\n const hasReceiveAmountQuoteIssue = Boolean(receiveAmountIssue);\n\n useEffect(() => {\n if (activeMode !== \"swap\" || swapStep !== \"idle\" || !nexusSDK) return;\n\n if (syncingIntentSourcesRef.current) {\n syncingIntentSourcesRef.current = false;\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n }\n\n if (hasReceiveAmountQuoteIssue) {\n clearPendingSwapIntent(true);\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n if (hasInsufficientSourcesQuoteIssue) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n const hasEnoughForQuote = hasReadyExactInSwapInput(fromTokens, toToken);\n\n if (!hasEnoughForQuote) {\n clearPendingSwapIntent();\n setSwapQuoteIssue(null);\n setTxError(null);\n return;\n }\n\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n return;\n }\n\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n setQuoteRefreshing(true);\n let quoteStarted = false;\n const quoteDelay = getQuoteRequestDelay();\n const timer = window.setTimeout(() => {\n quoteStarted = true;\n void handleEnterPreview({ background: true });\n }, quoteDelay);\n\n return () => {\n window.clearTimeout(timer);\n if (syncingIntentSourcesRef.current) return;\n if (!quoteStarted && swapStepRef.current === \"idle\") {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n }\n };\n }, [\n activeMode,\n activeQuoteInputKey,\n amount,\n defaultRecipientAddress,\n fromTokensQuoteKey,\n hasCurrentQuoteIntent,\n hasInsufficientSourcesQuoteIssue,\n hasReceiveAmountQuoteIssue,\n getQuoteRequestDelay,\n nexusSDK,\n recipientAddress,\n swapStep,\n toTokenQuoteKey,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"deposit\" || swapStep !== \"idle\" || !nexusSDK) return;\n\n if (syncingIntentSourcesRef.current) {\n syncingIntentSourcesRef.current = false;\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n }\n\n if (hasReceiveAmountQuoteIssue) {\n clearPendingSwapIntent(true);\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n if (hasInsufficientSourcesQuoteIssue) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n const parsedAmount = parseFiatNumber(amount);\n const hasEnoughForQuote = Boolean(\n parsedAmount?.gt(0) &&\n toToken &&\n selectedOpportunity &&\n depositTokenAmountForQuote,\n );\n\n if (!hasEnoughForQuote) {\n clearPendingSwapIntent();\n clearSelectedSources();\n return;\n }\n\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n return;\n }\n\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n setQuoteRefreshing(true);\n let quoteStarted = false;\n const quoteDelay = getQuoteRequestDelay();\n const timer = window.setTimeout(() => {\n quoteStarted = true;\n void handleEnterPreview({ background: true });\n }, quoteDelay);\n\n return () => {\n window.clearTimeout(timer);\n if (syncingIntentSourcesRef.current) return;\n if (!quoteStarted && swapStepRef.current === \"idle\") {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n }\n };\n }, [\n activeMode,\n amount,\n activeQuoteInputKey,\n depositAmountMode,\n depositQuoteAmountKey,\n hasCurrentQuoteIntent,\n hasInsufficientSourcesQuoteIssue,\n hasReceiveAmountQuoteIssue,\n getQuoteRequestDelay,\n nexusSDK,\n sourceSelectionRevision,\n selectedOpportunityIdentity,\n swapStep,\n toTokenQuoteKey,\n ]);\n\n useEffect(() => {\n if (activeMode !== \"send\" || swapStep !== \"idle\" || !nexusSDK) return;\n\n if (syncingIntentSourcesRef.current) {\n syncingIntentSourcesRef.current = false;\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n }\n\n if (hasReceiveAmountQuoteIssue) {\n clearPendingSwapIntent(true);\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n if (hasInsufficientSourcesQuoteIssue) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n return;\n }\n\n const parsedAmount = parseFiatNumber(amount);\n const hasEnoughForQuote = Boolean(parsedAmount?.gt(0) && toToken);\n\n if (!hasEnoughForQuote) {\n clearPendingSwapIntent();\n clearSelectedSources();\n return;\n }\n\n if (hasCurrentQuoteIntent) {\n setIntentLoading(false);\n setQuoteRefreshing(false);\n return;\n }\n\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n setQuoteRefreshing(true);\n let quoteStarted = false;\n const quoteDelay = getQuoteRequestDelay();\n const timer = window.setTimeout(() => {\n quoteStarted = true;\n void handleEnterPreview({ background: true });\n }, quoteDelay);\n\n return () => {\n window.clearTimeout(timer);\n if (syncingIntentSourcesRef.current) return;\n if (!quoteStarted && swapStepRef.current === \"idle\") {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n }\n };\n }, [\n activeMode,\n amount,\n activeQuoteInputKey,\n hasCurrentQuoteIntent,\n hasInsufficientSourcesQuoteIssue,\n hasReceiveAmountQuoteIssue,\n getQuoteRequestDelay,\n nexusSDK,\n sourceSelectionRevision,\n swapStep,\n toTokenQuoteKey,\n ]);\n\n const refreshActiveSwapIntent = useCallback(async () => {\n if (receiveAmountIssueRef.current) return;\n\n const activeIntent = swapIntentRef.current;\n if (\n !activeIntent ||\n intentLoading ||\n quoteRefreshing ||\n receiveMaxCalculating ||\n previewQuoteRefreshing\n ) {\n return;\n }\n\n const runId = activeIntent.runId;\n const quoteInputKey = activeIntent.quoteInputKey;\n if (!quoteInputKey || activeQuoteInputKeyRef.current !== quoteInputKey) {\n return;\n }\n const isPreviewRefresh = swapStepRef.current === \"preview-intent\";\n if (isPreviewRefresh) {\n setPreviewQuoteRefreshing(true);\n } else {\n setQuoteRefreshing(true);\n }\n try {\n const updatedRaw = await activeIntent.refresh();\n const updatedBridgeProvider = normalizeBridgeProvider(\n (updatedRaw as any)?.bridgeProvider ??\n (updatedRaw as any)?.normalizedIntent?.bridgeProvider ??\n (updatedRaw as any)?.swap?.bridgeProvider ??\n activeIntent.intent?.bridgeProvider,\n );\n const updated = normalizeRenderableSwapIntentData(\n updatedRaw,\n updatedBridgeProvider,\n );\n if (\n !updated ||\n swapRunIdRef.current !== runId ||\n activeQuoteInputKeyRef.current !== quoteInputKey\n ) {\n return;\n }\n\n if (swapIntentRef.current) {\n swapIntentRef.current.intent = updated;\n }\n applySwapIntent(updated);\n } catch (err) {\n console.error(\"Unable to refresh swap intent\", err);\n } finally {\n if (\n swapRunIdRef.current === runId &&\n activeQuoteInputKeyRef.current === quoteInputKey\n ) {\n if (isPreviewRefresh) {\n setPreviewQuoteRefreshing(false);\n } else {\n setQuoteRefreshing(false);\n }\n }\n }\n }, [\n applySwapIntent,\n intentLoading,\n previewQuoteRefreshing,\n quoteRefreshing,\n receiveMaxCalculating,\n ]);\n\n useEffect(() => {\n const hasRefreshableIntent =\n (activeMode === \"swap\" ||\n activeMode === \"deposit\" ||\n activeMode === \"send\") &&\n Boolean(\n intentData &&\n swapIntentRef.current &&\n swapIntentRef.current.quoteInputKey === activeQuoteInputKey,\n ) &&\n (swapStep === \"idle\" || swapStep === \"preview-intent\");\n\n if (!hasRefreshableIntent || receiveAmountIssue) {\n setQuoteRefreshProgress(0);\n setQuoteRefreshSecondsRemaining(0);\n return;\n }\n\n let cancelled = false;\n let timeout: number | undefined;\n\n const scheduleRefresh = () => {\n const quoteAge = Date.now() - lastSwapIntentRefreshAtRef.current;\n const delay = Math.max(0, QUOTE_REFRESH_INTERVAL_MS - quoteAge);\n timeout = window.setTimeout(() => {\n if (receiveAmountIssueRef.current) {\n clearPendingSwapIntent(true);\n setQuoteRefreshProgress(0);\n setQuoteRefreshSecondsRemaining(0);\n return;\n }\n\n if (\n intentLoading ||\n quoteRefreshing ||\n receiveMaxCalculating ||\n previewQuoteRefreshing\n ) {\n if (!cancelled) {\n timeout = window.setTimeout(scheduleRefresh, 1000);\n }\n return;\n }\n\n void refreshActiveSwapIntent().finally(() => {\n if (!cancelled) {\n scheduleRefresh();\n }\n });\n }, delay);\n };\n\n scheduleRefresh();\n\n return () => {\n cancelled = true;\n if (timeout !== undefined) {\n window.clearTimeout(timeout);\n }\n };\n }, [\n activeMode,\n activeQuoteInputKey,\n intentData,\n intentLoading,\n receiveAmountIssue,\n previewQuoteRefreshing,\n quoteRefreshing,\n receiveMaxCalculating,\n refreshActiveSwapIntent,\n swapStep,\n ]);\n\n useEffect(() => {\n const hasRefreshableIntent =\n (activeMode === \"swap\" ||\n activeMode === \"deposit\" ||\n activeMode === \"send\") &&\n Boolean(\n intentData &&\n swapIntentRef.current &&\n swapIntentRef.current.quoteInputKey === activeQuoteInputKey,\n ) &&\n (swapStep === \"idle\" || swapStep === \"preview-intent\");\n\n if (!hasRefreshableIntent || receiveAmountIssue) {\n setQuoteRefreshProgress(0);\n setQuoteRefreshSecondsRemaining(0);\n return;\n }\n\n const updateProgress = () => {\n const quoteAge = Date.now() - lastSwapIntentRefreshAtRef.current;\n const remaining = Math.max(0, QUOTE_REFRESH_INTERVAL_MS - quoteAge);\n setQuoteRefreshProgress(remaining / QUOTE_REFRESH_INTERVAL_MS);\n setQuoteRefreshSecondsRemaining(Math.ceil(remaining / 1000));\n };\n\n updateProgress();\n const interval = window.setInterval(updateProgress, 250);\n\n return () => window.clearInterval(interval);\n }, [\n activeMode,\n activeQuoteInputKey,\n intentData,\n receiveAmountIssue,\n swapStep,\n ]);\n\n /** User accepted swap from the preview — call allow() from the intent hook */\n const handleSwapAccept = () => {\n const activeIntent = swapIntentRef.current;\n if (activeIntent) {\n if (\n activeIntent.quoteInputKey &&\n activeQuoteInputKeyRef.current !== activeIntent.quoteInputKey\n ) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: true });\n setQuoteRefreshing(true);\n setSwapStep(\"idle\");\n return;\n }\n if (activeMode === \"deposit\") {\n previewConfirmedTsRef.current = Date.now();\n attemptCountRef.current += 1;\n const timeInPreviewMs = previewViewedTsRef.current\n ? previewConfirmedTsRef.current - previewViewedTsRef.current\n : 0;\n trackDeposit(\"deposit_preview_confirmed\", {\n timeInPreviewMs,\n totalFeeUsd: Number(intentFeeUsd) || 0,\n sourceCount: (intentData?.sources ?? []).length,\n });\n }\n onStart?.();\n startSwapHistoryEntry();\n setSwapStep(\"progress\");\n setQuoteRefreshing(false);\n resetProgressEvents();\n if (swapStepsListRef.current.length > 0) {\n seed(swapStepsListRef.current);\n } else {\n resetSteps();\n }\n activeIntent.allow();\n }\n };\n\n // ---------------------------------------------------------------------------\n // Header title\n // ---------------------------------------------------------------------------\n const isDepositMethodScreen =\n activeMode === \"deposit\" &&\n configuredEnableOnRamp &&\n swapStep === \"idle\" &&\n depositFundingStep === \"method\";\n const isDepositWalletScreen =\n activeMode === \"deposit\" &&\n swapStep === \"idle\" &&\n depositFundingStep === \"wallet\";\n const isDepositOnrampScreen =\n activeMode === \"deposit\" &&\n configuredEnableOnRamp &&\n swapStep === \"idle\" &&\n depositFundingStep === \"onramp\";\n const normalizedDepositOnrampSessionState =\n depositOnrampSessionState?.trim().toUpperCase() ?? \"\";\n const hasDepositOnrampSession =\n isDepositOnrampScreen && Boolean(depositOnrampSessionState);\n const getDepositOnrampSessionTitle = () => {\n if (\n [\"DEPOSIT_COMPLETE\", \"DEPOSIT_SUCCESS\", \"DEPOSITED\"].includes(\n normalizedDepositOnrampSessionState,\n )\n ) {\n return \"Success\";\n }\n if (\n [\"FAILED\", \"DECLINED\", \"AUTHORIZATION_EXPIRED\"].includes(\n normalizedDepositOnrampSessionState,\n )\n ) {\n return \"Payment failed\";\n }\n if (\n [\n \"DEPOSIT_ATTENTION\",\n \"DEPOSIT_FAILED\",\n \"DEPOSIT_REQUIRES_ATTENTION\",\n ].includes(normalizedDepositOnrampSessionState)\n ) {\n return \"Deposit needs your attention\";\n }\n if (normalizedDepositOnrampSessionState === \"CANCELLED\") {\n return \"Payment cancelled\";\n }\n if (normalizedDepositOnrampSessionState === \"REFUNDED\") {\n return \"Payment refunded\";\n }\n if (normalizedDepositOnrampSessionState === \"EXPIRED\") {\n return \"Payment expired\";\n }\n if (\n [\n \"SETTLED\",\n \"COMPLETING_DEPOSIT\",\n \"DEPOSIT_PROCESSING\",\n \"DEPOSITING\",\n \"SWAPPING_GAS\",\n ].includes(normalizedDepositOnrampSessionState)\n ) {\n return \"Completing your deposit\";\n }\n if (\n normalizedDepositOnrampSessionState === \"PROCESSING\" ||\n normalizedDepositOnrampSessionState === \"SETTLING\"\n ) {\n return \"Processing your payment\";\n }\n if (normalizedDepositOnrampSessionState === \"ONRAMP_CALLBACK_RECEIVED\") {\n return \"Deposit\";\n }\n return \"Continue on Other Window\";\n };\n\n const getTitle = () => {\n const configuredWidgetHeading = normalizeConfiguredString(\n appearanceConfig?.widgetHeading,\n );\n if (swapStep === \"history\") return \"Transaction History\";\n // Drawer panels overlay the main page,\n // so the header should still show the main page title.\n\n if (swapStep === \"preview-intent\") {\n return activeMode === \"deposit\"\n ? \"Confirm Deposit\"\n : activeMode === \"send\"\n ? \"Confirm Send\"\n : \"Confirm Swap\";\n }\n\n if (activeMode === \"swap\") {\n if (swapStep === \"progress\") return \"Swapping…\";\n if (swapStep === \"success\") return \"Swap Complete\";\n if (swapStep === \"failed\" && currentSwapEntry?.status === \"timeout\") {\n return TIMEOUT_LABEL;\n }\n if (swapStep === \"failed\") return \"Swap Failed\";\n return configuredWidgetHeading ?? \"Swap and Bridge\";\n }\n if (activeMode === \"deposit\") {\n if (isDepositOnrampScreen) {\n return hasDepositOnrampSession\n ? getDepositOnrampSessionTitle()\n : \"Payment Amount\";\n }\n if (swapStep === \"progress\") return \"Depositing…\";\n if (swapStep === \"success\") return \"Deposit Complete\";\n if (swapStep === \"failed\" && currentSwapEntry?.status === \"timeout\") {\n return TIMEOUT_LABEL;\n }\n if (swapStep === \"failed\") return \"Deposit Failed\";\n return configuredWidgetHeading ?? \"Deposit\";\n }\n if (activeMode === \"send\") {\n if (swapStep === \"progress\") return \"Sending…\";\n if (swapStep === \"success\") return \"Send Complete\";\n if (swapStep === \"failed\" && currentSwapEntry?.status === \"timeout\") {\n return TIMEOUT_LABEL;\n }\n if (swapStep === \"failed\") return \"Send Failed\";\n return configuredWidgetHeading ?? \"Send\";\n }\n return configuredWidgetHeading ?? \"Nexus Widget\";\n };\n\n // Titles that should be center-aligned (main screens / confirm screens)\n // Left-aligned: choose-swap-asset, choose-receive-asset (sub-screens with subtitles)\n const isTitleCentered = () => {\n if (swapStep === \"history\") return false;\n return true; // idle, drawer panels, preview-intent, progress, etc.\n };\n\n const canGoBack =\n swapStep === \"preview-intent\" ||\n swapStep === \"history\" ||\n (isDepositWalletScreen && configuredEnableOnRamp) ||\n (isDepositOnrampScreen && !hasDepositOnrampSession);\n const showHistoryButton = !isDepositOnrampScreen;\n const handleBack = () => {\n if (\n activeMode === \"deposit\" &&\n configuredEnableOnRamp &&\n swapStep === \"idle\" &&\n depositFundingStep !== \"method\"\n ) {\n setDepositFundingStep(\"method\");\n return;\n }\n if (swapStep === \"history\") {\n setSwapStep(\"idle\");\n return;\n }\n if (swapStep === \"choose-swap-asset\") {\n handleSourcePickerCancel();\n return;\n }\n if (swapStep === \"choose-receive-asset\") {\n closeDrawerToIdle();\n return;\n }\n if (swapStep === \"enter-recipient\") {\n closeDrawerToIdle();\n return;\n }\n if (swapStep === \"preview-intent\") {\n const canRequoteAfterPreviewBack =\n activeMode === \"swap\"\n ? hasReadyExactInSwapInput(fromTokens, toToken)\n : canRefreshExactOutQuote();\n\n if (\n canRequoteAfterPreviewBack &&\n (activeMode === \"deposit\" || activeMode === \"send\")\n ) {\n setExactOutQuoteSourceModeValue(\"all\");\n }\n if (activeMode === \"deposit\" || activeMode === \"send\") {\n invalidateExactOutQuoteForRefresh();\n } else {\n clearPendingSwapIntent(true, {\n keepQuoteRefreshing: canRequoteAfterPreviewBack,\n });\n }\n if (canRequoteAfterPreviewBack && activeMode === \"swap\") {\n setQuoteRefreshing(true);\n setTxError(null);\n setSwapQuoteIssue(null);\n }\n setSwapStep(\"idle\");\n return;\n }\n if (swapStep === \"progress\") {\n return;\n } // can't go back during tx\n setSwapStep(\"idle\");\n };\n\n const handleSwapAmountChange = (val: string, panel: \"send\" | \"receive\") => {\n if (isConfiguredAmountFixed) return;\n syncingIntentSourcesRef.current = false;\n setSwapQuoteIssue(null);\n setTxError(null);\n const nextAmount = parseFiatNumber(val);\n const receiveIssue = buildReceiveAmountIssue({ inputAmount: val });\n applyReceiveAmountIssue(receiveIssue);\n const hasSelectedSourceToken = fromTokens.some(\n (token) => token.chainId && token.contractAddress,\n );\n const shouldLoadQuote = Boolean(\n !receiveIssue &&\n nexusSDK &&\n nextAmount?.gt(0) &&\n toToken &&\n hasSelectedSourceToken,\n );\n if (!receiveIssue) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: shouldLoadQuote });\n }\n if (shouldLoadQuote) {\n setQuoteRefreshing(true);\n }\n setAmount(val);\n if (panel === \"receive\") {\n setFromTokens((prev) =>\n prev.map((token) => ({ ...token, userAmount: \"\" })),\n );\n }\n // Nexus Widget swaps are exact-in only. Exact-out is reserved for Deposit and Send.\n if (swapType !== \"exactIn\") {\n setSwapType(\"exactIn\");\n }\n };\n\n const handleSwapTokensUpdate = (tokens: SwapTokenOption[]) => {\n setSwapQuoteIssue(null);\n setTxError(null);\n applyReceiveAmountIssue(buildReceiveAmountIssue({ sourceTokens: tokens }));\n setFromTokens(tokens);\n };\n\n const handleDepositAmountChange = (val: string) => {\n if (isConfiguredAmountFixed) return;\n syncingIntentSourcesRef.current = false;\n resetExactOutSourcesToAuto();\n maxPercentRunRef.current += 1;\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setSwapQuoteIssue(null);\n const nextAmount = parseFiatNumber(val);\n const receiveIssue = buildReceiveAmountIssue({ inputAmount: val });\n applyReceiveAmountIssue(receiveIssue);\n const shouldLoadQuote = Boolean(\n !receiveIssue &&\n nexusSDK &&\n nextAmount?.gt(0) &&\n toToken &&\n selectedOpportunity,\n );\n if (!receiveIssue) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: shouldLoadQuote });\n }\n if (shouldLoadQuote) {\n setQuoteRefreshing(true);\n } else {\n clearSelectedSources();\n }\n setAmount(val);\n };\n\n const handleSendAmountChange = (val: string) => {\n if (isConfiguredAmountFixed) return;\n syncingIntentSourcesRef.current = false;\n resetExactOutSourcesToAuto();\n maxPercentRunRef.current += 1;\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setSwapQuoteIssue(null);\n setSwapType(\"exactOut\");\n const nextAmount = parseFiatNumber(val);\n const receiveIssue = buildReceiveAmountIssue({\n inputAmount: val,\n type: \"exactOut\",\n });\n applyReceiveAmountIssue(receiveIssue);\n const shouldLoadQuote = Boolean(\n !receiveIssue && nexusSDK && nextAmount?.gt(0) && toToken,\n );\n if (!receiveIssue) {\n clearPendingSwapIntent(true, { keepQuoteRefreshing: shouldLoadQuote });\n }\n if (shouldLoadQuote) {\n setQuoteRefreshing(true);\n } else {\n clearSelectedSources();\n }\n setAmount(val);\n };\n\n const handleDepositAmountModeToggle = () => {\n if (isConfiguredAmountFixed) return;\n syncingIntentSourcesRef.current = false;\n resetExactOutSourcesToAuto();\n const rate = getDepositTokenUsdRate();\n const parsedAmount = parseFiatNumber(amount) ?? new Decimal(0);\n if (parsedAmount.gt(0) && rate.gt(0)) {\n const converted =\n depositAmountMode === \"token\"\n ? parsedAmount.mul(rate).toDecimalPlaces(2)\n : parsedAmount\n .div(rate)\n .toDecimalPlaces(\n getCappedTokenDisplayDecimals(toToken?.decimals),\n Decimal.ROUND_DOWN,\n );\n setAmount(converted.toFixed());\n }\n clearPendingSwapIntent();\n setDepositAmountMode((current) => (current === \"token\" ? \"usd\" : \"token\"));\n };\n\n const handleDepositPercentSelect = async (pct: number) => {\n if (isConfiguredAmountFixed) return;\n if (!toToken) return;\n\n syncingIntentSourcesRef.current = false;\n setTxError(null);\n setSwapQuoteIssue(null);\n const runId = ++maxPercentRunRef.current;\n lastInputMethodRef.current =\n pct === 20\n ? \"percent_20\"\n : pct === 25\n ? \"percent_25\"\n : pct === 50\n ? \"percent_50\"\n : pct === 75\n ? \"percent_75\"\n : \"percent_max\";\n\n if (pct !== 100) {\n const nextAmount = getExactOutPercentAmountFromBalance(\n toToken,\n pct,\n depositAmountMode === \"usd\",\n );\n\n if (nextAmount) {\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setDepositAmountMode(nextAmount.mode);\n handleDepositAmountChange(nextAmount.amount);\n return;\n }\n\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setTxError(\"Unable to calculate this percentage for the deposit asset.\");\n return;\n }\n\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n const maxAmount = getExactOutPercentAmountFromBalance(\n toToken,\n 100,\n depositAmountMode === \"usd\",\n );\n if (runId !== maxPercentRunRef.current) return;\n if (!maxAmount) {\n setTxError(\"No depositable amount is available for this deposit.\");\n return;\n }\n\n setDepositAmountMode(maxAmount.mode);\n handleDepositAmountChange(maxAmount.amount);\n };\n\n const handleSendPercentSelect = async (pct: number) => {\n if (isConfiguredAmountFixed) return;\n if (!toToken) return;\n\n syncingIntentSourcesRef.current = false;\n setTxError(null);\n setSwapQuoteIssue(null);\n const runId = ++maxPercentRunRef.current;\n lastInputMethodRef.current =\n pct === 20\n ? \"percent_20\"\n : pct === 25\n ? \"percent_25\"\n : pct === 50\n ? \"percent_50\"\n : pct === 75\n ? \"percent_75\"\n : \"percent_max\";\n\n if (pct !== 100) {\n const nextAmount = getExactOutPercentAmountFromBalance(\n toToken,\n pct,\n false,\n );\n\n if (nextAmount) {\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n handleSendAmountChange(nextAmount.amount);\n return;\n }\n\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n setTxError(\"Unable to calculate this percentage for the send asset.\");\n return;\n }\n\n setQuoteRefreshing(false);\n setReceiveMaxCalculating(false);\n setMaxCalculationPercent(null);\n const maxAmount = getExactOutPercentAmountFromBalance(toToken, 100, false);\n if (runId !== maxPercentRunRef.current) return;\n if (!maxAmount) {\n setTxError(\"No transferable amount is available for this asset.\");\n return;\n }\n\n handleSendAmountChange(maxAmount.amount);\n };\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n const insufficientSourceIssue =\n swapQuoteIssue?.type === \"insufficientSources\" ? swapQuoteIssue : null;\n const configuredAmountIssue = buildConfiguredAmountIssue();\n const blockingQuoteIssue =\n insufficientSourceIssue ?? receiveAmountIssue ?? configuredAmountIssue;\n const isExactOutPaymentFlow =\n activeMode === \"deposit\" || activeMode === \"send\";\n const hasCurrentRunnableIntent = hasCurrentQuoteIntent;\n const hasIntentSources = Boolean((intentData?.sources ?? []).length > 0);\n const hasCurrentExactOutPaymentIntent =\n hasCurrentRunnableIntent &&\n (hasIntentSources ||\n (isExactOutPaymentFlow && Boolean(intentData?.destination)));\n const isExactOutRouteLoading =\n isExactOutPaymentFlow &&\n swapStep === \"idle\" &&\n swapType === \"exactOut\" &&\n Boolean(\n toToken && (receiveMaxCalculating || (amount && Number(amount) > 0)),\n ) &&\n !blockingQuoteIssue &&\n !hasCurrentExactOutPaymentIntent &&\n (quoteRefreshing || intentLoading || receiveMaxCalculating);\n const isQuoteUnavailableForAutoSourceFlow =\n isExactOutPaymentFlow &&\n Boolean(hasPositiveDecimalInput(amount) && toToken) &&\n !quoteRefreshing &&\n !receiveMaxCalculating &&\n !intentLoading &&\n !blockingQuoteIssue &&\n !hasCurrentExactOutPaymentIntent;\n const hasPositiveRootAmount = hasPositiveDecimalInput(amount);\n const hasReadySwapQuoteInput = hasReadyExactInSwapInput(fromTokens, toToken);\n const needsWalletConnection = !ownerAddress || !nexusSDK;\n const isExactOutPaymentQuotePending =\n isExactOutPaymentFlow && (quoteRefreshing || intentLoading);\n const walletConnectBusy =\n walletActionPending ||\n nexusLoading ||\n isWalletConnectPending ||\n walletStatus === \"connecting\";\n const hasConnectWalletHandler = Boolean(\n onConnectClick || onConnectWallet || connectors.length > 0,\n );\n const walletCtaLabel = hasConnectWalletHandler\n ? walletConnectBusy\n ? \"Connecting...\"\n : \"Connect Wallet\"\n : \"Connect your wallet to proceed\";\n const isSwapCtaDisabled = needsWalletConnection\n ? !hasConnectWalletHandler || walletConnectBusy\n : !hasReadySwapQuoteInput ||\n receiveMaxCalculating ||\n quoteRefreshing ||\n Boolean(blockingQuoteIssue);\n const isDepositCtaDisabled = needsWalletConnection\n ? !hasConnectWalletHandler || walletConnectBusy\n : !hasPositiveRootAmount ||\n !toToken ||\n receiveMaxCalculating ||\n isExactOutPaymentQuotePending ||\n (!hasCurrentExactOutPaymentIntent &&\n isQuoteUnavailableForAutoSourceFlow) ||\n Boolean(blockingQuoteIssue);\n const sendNeedsRecipient = activeMode === \"send\" && !recipientAddress;\n const isSendCtaDisabled = needsWalletConnection\n ? !hasConnectWalletHandler || walletConnectBusy\n : !hasPositiveRootAmount ||\n !toToken ||\n hasSameOwnerSendRecipient ||\n receiveMaxCalculating ||\n (!sendNeedsRecipient &&\n (isExactOutPaymentQuotePending ||\n (!hasCurrentExactOutPaymentIntent &&\n isQuoteUnavailableForAutoSourceFlow))) ||\n Boolean(blockingQuoteIssue);\n const quoteCtaLabel = (fallback: string) => {\n if (needsWalletConnection) return walletCtaLabel;\n if (insufficientSourceIssue) return \"Insufficient balance\";\n if (receiveAmountIssue) return receiveAmountIssue.ctaLabel;\n if (configuredAmountIssue) return configuredAmountIssue.ctaLabel;\n if (receiveMaxCalculating) return \"Calculating...\";\n if (\n isExactOutPaymentQuotePending ||\n (!hasCurrentExactOutPaymentIntent && (quoteRefreshing || intentLoading))\n ) {\n return \"Fetching quotes...\";\n }\n if (isQuoteUnavailableForAutoSourceFlow) return \"Quote unavailable\";\n if (!hasPositiveRootAmount) return \"Enter amount\";\n return fallback;\n };\n const sendCtaLabel = (() => {\n if (needsWalletConnection) return walletCtaLabel;\n if (insufficientSourceIssue) return \"Insufficient balance\";\n if (receiveAmountIssue) return receiveAmountIssue.ctaLabel;\n if (configuredAmountIssue) return configuredAmountIssue.ctaLabel;\n if (!hasPositiveRootAmount) return \"Enter amount\";\n if (!toToken) return \"Select token\";\n if (hasSameOwnerSendRecipient) return \"Change recipient\";\n if (sendNeedsRecipient) return \"Add recipient\";\n return quoteCtaLabel(\"Review send\");\n })();\n const previewIntentSourceUsdNumber = (intentData?.sources ?? []).reduce(\n (sum, source) =>\n sum.plus(parseFiatNumber((source as any).value) ?? new Decimal(0)),\n new Decimal(0),\n );\n const previewSourceUsdNumber = previewIntentSourceUsdNumber.gt(0)\n ? previewIntentSourceUsdNumber\n : fromTokens.length > 0\n ? fromTokens.reduce(\n (sum, token) =>\n sum.plus(\n getTokenUsdValue(\n token,\n swapType === \"exactIn\" && fromTokens.length === 1\n ? amount\n : undefined,\n ),\n ),\n new Decimal(0),\n )\n : undefined;\n const previewExactOutDestinationAmount =\n activeMode === \"deposit\"\n ? depositTokenAmountForQuote\n : activeMode === \"send\"\n ? parseFiatNumber(amount)\n : undefined;\n const previewExactOutDestinationUsdNumber =\n activeMode === \"deposit\"\n ? depositUsdDecimal\n : activeMode === \"send\" && amount && toToken\n ? getTokenUsdValue(\n {\n ...toToken,\n userAmount: amount,\n userAmountMode: \"token\",\n },\n amount,\n )\n : undefined;\n const previewDestinationUsdNumber =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n previewExactOutDestinationUsdNumber?.gt(0)\n ? previewExactOutDestinationUsdNumber\n : parseFiatNumber((intentData?.destination as any)?.value);\n const previewDestinationAmount =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n previewExactOutDestinationAmount?.gt(0)\n ? previewExactOutDestinationAmount\n .toDecimalPlaces(toToken?.decimals ?? 18, Decimal.ROUND_DOWN)\n .toFixed()\n : intentToAmount;\n const previewFromAmountUsd =\n previewSourceUsdNumber && previewSourceUsdNumber.gt(0)\n ? previewSourceUsdNumber.toDecimalPlaces(6).toFixed()\n : undefined;\n const previewToAmountUsd =\n previewDestinationUsdNumber && previewDestinationUsdNumber.gt(0)\n ? previewDestinationUsdNumber.toDecimalPlaces(6).toFixed()\n : undefined;\n const previewDestinationGasFeeUsd = (() => {\n const value = getIntentDestinationGasUsdValue(intentData);\n return value && value.gt(0)\n ? value.toDecimalPlaces(6, Decimal.ROUND_DOWN).toFixed()\n : undefined;\n })();\n const predictiveExactInQuote =\n predictiveQuote?.mode === \"exactIn\" &&\n predictiveQuote.key === getPredictiveQuoteCacheKey(\"swap\", \"exactIn\")\n ? predictiveQuote\n : null;\n const predictiveExactOutQuote =\n predictiveQuote?.mode === \"exactOut\" &&\n predictiveQuote.key === getPredictiveQuoteCacheKey(activeMode, \"exactOut\")\n ? predictiveQuote\n : null;\n const shouldUseCurrentExactOutIntentSources =\n isExactOutPaymentFlow && hasCurrentQuoteIntent && hasIntentSources;\n const currentExactOutIntentSourceTokens =\n shouldUseCurrentExactOutIntentSources\n ? sortSwapTokensByUsdDesc(\n (intentData?.sources ?? [])\n .map(buildIntentSourceToken)\n .filter(hasPositiveSourceSpend),\n )\n : [];\n const resolvedToToken =\n toToken ??\n (activeMode === \"deposit\" && selectedOpportunity\n ? toTokenFromOpportunity(selectedOpportunity)\n : undefined);\n const enrichedResolvedToToken = enrichTokenOptionLogo(resolvedToToken);\n const toTokenWithFetchedBalance =\n enrichedResolvedToToken && destinationBalance\n ? { ...enrichedResolvedToToken, balance: destinationBalance }\n : enrichedResolvedToToken;\n const idleReceiveQuoteAmount =\n activeMode === \"swap\" && swapType === \"exactIn\"\n ? (intentToAmount ?? predictiveExactInQuote?.toAmount)\n : undefined;\n const idleReceiveQuoteUsd =\n activeMode === \"swap\" && swapType === \"exactIn\"\n ? (previewToAmountUsd ?? predictiveExactInQuote?.toUsd)\n : previewToAmountUsd;\n const exactOutDestinationCoverage = getExactOutDestinationBalanceCoverage({\n requestedAmount: previewExactOutDestinationAmount,\n requestedUsd: previewExactOutDestinationUsdNumber,\n producedAmount: hasIntentSources\n ? parseFiatNumber(intentData?.destination?.amount)\n : undefined,\n producedUsd: hasIntentSources\n ? parseFiatNumber(intentData?.destination?.value)\n : undefined,\n token: toTokenWithFetchedBalance,\n });\n const destinationBalanceDisplayToken = buildDestinationBalanceDisplayToken(\n exactOutDestinationCoverage,\n toTokenWithFetchedBalance,\n );\n const shouldShowPredictiveExactOutDisplay =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n (quoteRefreshing || intentLoading) &&\n !hasIntentSources &&\n Boolean(\n predictiveExactOutQuote &&\n ((predictiveExactOutQuote.sources?.length ?? 0) > 0 ||\n destinationBalanceDisplayToken),\n );\n const baseDisplayFromTokens = shouldUseCurrentExactOutIntentSources\n ? currentExactOutIntentSourceTokens\n : shouldShowPredictiveExactOutDisplay\n ? (predictiveExactOutQuote?.sources ?? fromTokens)\n : fromTokens;\n const displayFromTokens = (() => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") {\n return baseDisplayFromTokens;\n }\n if (!destinationBalanceDisplayToken) {\n return mergeDisplaySourceTokens(\n sortDisplaySourcesByBalanceUsdDesc(baseDisplayFromTokens),\n );\n }\n\n const destinationKey = getTokenSelectionKey(destinationBalanceDisplayToken);\n let replacedEmptyDestinationToken = false;\n const tokens = baseDisplayFromTokens.map((token) => {\n const isDestinationToken = getTokenSelectionKey(token) === destinationKey;\n if (\n isDestinationToken &&\n !hasPositiveDecimalInput(token.userAmount) &&\n !hasPositiveDecimalInput(token.userAmountUsd)\n ) {\n replacedEmptyDestinationToken = true;\n return destinationBalanceDisplayToken;\n }\n return token;\n });\n\n const displayTokens = replacedEmptyDestinationToken\n ? tokens\n : [...tokens, destinationBalanceDisplayToken];\n return mergeDisplaySourceTokens(\n sortDisplaySourcesByBalanceUsdDesc(displayTokens),\n );\n })();\n const displayExactOutRouteLoading =\n isExactOutRouteLoading && !shouldShowPredictiveExactOutDisplay;\n const isSourcePickerRefreshDisabled =\n quoteRefreshing || intentLoading || previewQuoteRefreshing;\n const isIntentSourceUiActionable =\n activeMode === \"deposit\"\n ? !isDepositCtaDisabled\n : activeMode === \"send\"\n ? !isSendCtaDisabled\n : !isSwapCtaDisabled;\n\n useEffect(() => {\n if (!intentFetchTiming?.endTimeMs) {\n return;\n }\n if (latestIntentFetchRunIdRef.current !== intentFetchTiming.runId) {\n return;\n }\n if (intentUiRenderLoggedRunIdRef.current === intentFetchTiming.runId) {\n return;\n }\n const hasRenderedSources =\n displayFromTokens.length > 0 ||\n hasIntentSources ||\n Boolean(intentData?.destination);\n if (!hasRenderedSources) return;\n if (\n isSwapBalancePending ||\n isSourcePickerRefreshDisabled ||\n quoteRefreshing ||\n intentLoading ||\n previewQuoteRefreshing ||\n receiveMaxCalculating ||\n displayExactOutRouteLoading ||\n !isIntentSourceUiActionable\n ) {\n return;\n }\n\n const renderTimeMs = Date.now();\n const renderDurationMs = renderTimeMs - intentFetchTiming.startTimeMs;\n const fetchDurationMs =\n intentFetchTiming.fetchDurationMs ??\n intentFetchTiming.endTimeMs - intentFetchTiming.startTimeMs;\n const differenceMs = renderDurationMs - fetchDurationMs;\n\n console.log(\"[NexusWidget] intent sources UI render complete\", {\n runId: intentFetchTiming.runId,\n walletAddress: intentFetchTiming.walletAddress,\n operation: intentFetchTiming.operation,\n quoteInputKey: intentFetchTiming.quoteInputKey,\n sourceCount: displayFromTokens.length,\n dateNow: renderTimeMs,\n date: new Date(renderTimeMs),\n totalRenderTimeSeconds: renderDurationMs / 1000,\n elapsedMs: renderDurationMs,\n });\n console.log(\"[NexusWidget] intent render/fetch difference\", {\n runId: intentFetchTiming.runId,\n walletAddress: intentFetchTiming.walletAddress,\n operation: intentFetchTiming.operation,\n quoteInputKey: intentFetchTiming.quoteInputKey,\n differenceMs,\n dateNow: renderTimeMs,\n date: new Date(renderTimeMs),\n });\n intentUiRenderLoggedRunIdRef.current = intentFetchTiming.runId;\n }, [\n displayExactOutRouteLoading,\n displayFromTokens.length,\n hasIntentSources,\n intentLoading,\n intentData?.destination,\n intentFetchTiming,\n isDepositCtaDisabled,\n isIntentSourceUiActionable,\n isSendCtaDisabled,\n isSourcePickerRefreshDisabled,\n isSwapCtaDisabled,\n isSwapBalancePending,\n previewQuoteRefreshing,\n quoteRefreshing,\n receiveMaxCalculating,\n ]);\n\n const totalSwapBalanceUsd = getActiveTotalBalanceUsd()\n .toDecimalPlaces(2)\n .toFixed();\n const requestedOutputUsd =\n amount && toToken\n ? getTokenUsdValue(\n {\n ...toToken,\n userAmount: amount,\n userAmountMode: \"token\",\n },\n amount,\n )\n : new Decimal(0);\n const sendAmountUsd = requestedOutputUsd.toNumber();\n const exactOutRequiredUsdAmount = (() => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return undefined;\n\n const issueMissingUsd = parseFiatNumber(\n insufficientSourceIssue?.missingUsd,\n );\n if (issueMissingUsd && issueMissingUsd.gt(0)) {\n return getExactOutAvailableSourceUsd().plus(issueMissingUsd);\n }\n\n const requiredFundingUsd = getExactOutRequiredFundingUsd();\n if (requiredFundingUsd?.gt(0)) return requiredFundingUsd;\n\n if (requestedOutputUsd.gt(0)) return requestedOutputUsd;\n\n return undefined;\n })();\n const exactOutRequiredUsdDisplay = exactOutRequiredUsdAmount\n ?.toDecimalPlaces(2)\n .toFixed();\n const assetSelectorRequiredUsdDisplay =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n (swapStep === \"choose-swap-asset\" ||\n closingDrawerStep === \"choose-swap-asset\")\n ? (sourceSelectionRequiredUsdDisplay ?? exactOutRequiredUsdDisplay)\n : exactOutRequiredUsdDisplay;\n const captureSourceSelectionRequiredUsd = () => {\n if (activeMode !== \"deposit\" && activeMode !== \"send\") return;\n setSourceSelectionRequiredUsdDisplay(exactOutRequiredUsdDisplay);\n };\n const isIdleSwapQuoteLoading =\n activeMode === \"swap\" &&\n swapStep === \"idle\" &&\n (quoteRefreshing || intentLoading);\n const isReceiveAmountLoading =\n receiveMaxCalculating ||\n (isIdleSwapQuoteLoading &&\n swapType === \"exactIn\" &&\n !idleReceiveQuoteAmount);\n const isReceiveUsdLoading =\n receiveMaxCalculating ||\n (isIdleSwapQuoteLoading && swapType === \"exactIn\" && !idleReceiveQuoteUsd);\n const hasQuoteRefreshCountdown =\n (activeMode === \"swap\" ||\n activeMode === \"deposit\" ||\n activeMode === \"send\") &&\n hasCurrentQuoteIntent &&\n (swapStep === \"idle\" || swapStep === \"preview-intent\");\n const isRecipientDrawerClosing = closingDrawerStep === \"enter-recipient\";\n const isSwapAssetDrawerClosing = closingDrawerStep === \"choose-swap-asset\";\n const isReceiveAssetDrawerClosing =\n closingDrawerStep === \"choose-receive-asset\";\n const isReceiveAssetPickerLocked =\n activeMode === \"deposit\"\n ? configuredDepositOptions.length <= 1\n : (config.allowedDestinationPairs?.length ?? 0) === 1;\n const hideDestinationTokenDropdownIcon =\n activeMode === \"deposit\"\n ? configuredDepositOptions.length === 1\n : (config.allowedDestinationPairs?.length ?? 0) === 1;\n const isTokenAssetDrawerActive =\n swapStep === \"choose-swap-asset\" ||\n swapStep === \"choose-receive-asset\" ||\n closingDrawerStep === \"choose-swap-asset\" ||\n closingDrawerStep === \"choose-receive-asset\";\n const configuredReceiveTokenCount =\n activeMode === \"deposit\" || activeMode === \"send\"\n ? Math.max(\n configuredDestinationTokenOptions.length,\n config.allowedDestinationPairs?.length ?? 0,\n )\n : 0;\n const isConfiguredReceiveAssetDrawerActive =\n (activeMode === \"deposit\" || activeMode === \"send\") &&\n (swapStep === \"choose-receive-asset\" ||\n closingDrawerStep === \"choose-receive-asset\") &&\n Boolean(config.allowedDestinationPairs?.length);\n const tokenAssetDrawerMinRootContentHeight =\n isConfiguredReceiveAssetDrawerActive\n ? getConfiguredReceiveSelectorRootHeight(configuredReceiveTokenCount)\n : isTokenAssetDrawerActive\n ? TOKEN_SELECTOR_MIN_ROOT_CONTENT_HEIGHT\n : 0;\n const isDrawerOverlayActive =\n swapStep === \"choose-swap-asset\" ||\n swapStep === \"choose-receive-asset\" ||\n swapStep === \"enter-recipient\" ||\n closingDrawerStep !== null;\n const isPreviewIntentScreen = swapStep === \"preview-intent\";\n const displayedRootContentHeight =\n hasMeasuredRootContent && rootContentHeight\n ? Math.max(rootContentHeight, tokenAssetDrawerMinRootContentHeight)\n : null;\n\n const widgetContent = (\n {\n const transitions = [];\n if (hasMeasuredRootContent && shouldAnimateRootHeight) {\n transitions.push(`height ${ROOT_HEIGHT_TRANSITION_MS}ms ease-out`);\n }\n return transitions.join(\", \");\n })(),\n willChange: \"height\",\n width: \"450px\",\n maxWidth: \"100%\",\n minWidth: \"320px\",\n WebkitFontSmoothing: \"antialiased\",\n MozOsxFontSmoothing: \"grayscale\",\n }}\n >\n \n \n \n \n \n {canGoBack && (\n \n \n \n )}\n \n \n {getTitle()}\n \n {isDepositMethodScreen && (\n \n Select a funding method\n \n )}\n \n\n {/* Sub-screen asset counts */}\n {!isTitleCentered() &&\n activeMode === \"swap\" &&\n swapStep === \"choose-swap-asset\" &&\n swapType === \"exactIn\" && (\n \n {fromTokens.length} asset(s) selected\n \n )}\n \n\n {/* Right side icons */}\n \n {hasQuoteRefreshCountdown && (\n \n )}\n {showHistoryButton && (\n setSwapStep(\"history\")}\n style={{\n alignItems: \"center\",\n backgroundColor: theme.primitives.iconButton.backgroundColor,\n borderColor: theme.primitives.iconButton.borderColor,\n borderRadius: theme.radius.iconButton,\n borderStyle: \"solid\",\n borderWidth: \"1px\",\n boxShadow: theme.primitives.iconButton.boxShadow,\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n height: \"28px\",\n justifyContent: \"center\",\n width: \"28px\",\n cursor: \"pointer\",\n padding: 0,\n }}\n >\n \n \n \n \n \n \n )}\n {showCloseButton && (\n \n \n \n \n \n )}\n \n \n\n {/* ------------------------------------------------------------------ */}\n {/* Main content area */}\n {/* ------------------------------------------------------------------ */}\n \n {/* =============================================================== */}\n {/* SHARED SUB-SCREENS (non-drawer panels) */}\n {/* =============================================================== */}\n {(activeMode === \"swap\" ||\n activeMode === \"send\" ||\n activeMode === \"deposit\") &&\n swapStep !== \"idle\" &&\n swapStep !== \"choose-swap-asset\" &&\n swapStep !== \"choose-receive-asset\" &&\n swapStep !== \"enter-recipient\" && (\n <>\n {/* Panel: preview. */}\n {swapStep === \"preview-intent\" && (\n \n {\n clearPendingSwapIntent();\n setSwapStep(\"idle\");\n }}\n onTransitionChange={setIsPreviewTransitioning}\n opportunity={selectedOpportunity}\n recipientAddress={transferRecipientAddress}\n steps={steps}\n supportedTokenAssets={supportedChainsAndTokens}\n swapBalances={swapBalance}\n swapType={swapType}\n toAmount={previewDestinationAmount}\n toAmountTokens={\n previewDestinationAmount\n ? `${previewDestinationAmount}`\n : undefined\n }\n toAmountUsd={previewToAmountUsd}\n toToken={toTokenWithFetchedBalance}\n totalFeeUsd={intentFeeUsd}\n />\n \n )}\n\n {swapStep === \"progress\" && (\n \n )}\n\n {(swapStep === \"success\" || swapStep === \"failed\") &&\n currentSwapEntry && (\n
\n \n
\n )}\n \n )}\n\n {/* =============================================================== */}\n {/* HISTORY SCREEN */}\n {/* =============================================================== */}\n {swapStep === \"history\" && (\n \n )}\n\n {/* =============================================================== */}\n {/* SWAP IDLE SCREEN */}\n {/* =============================================================== */}\n {activeMode === \"swap\" &&\n [\n \"idle\",\n \"choose-swap-asset\",\n \"choose-receive-asset\",\n \"enter-recipient\",\n ].includes(swapStep) && (\n <>\n {\n handleSwapAmountChange(val, panel);\n }}\n onOpenDestPicker={() =>\n openDrawerStep(\"choose-receive-asset\")\n }\n onOpenRecipientPicker={handleOpenRecipientEditor}\n onOpenSourcePicker={(index) => {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n setEditingAssetIndex(index ?? null);\n beginSourcePickerEdit();\n openDrawerStep(\"choose-swap-asset\");\n }}\n onUpdateTokens={handleSwapTokensUpdate}\n receiveQuoteAmount={\n swapType === \"exactIn\" ? idleReceiveQuoteAmount : undefined\n }\n receiveQuoteUsd={idleReceiveQuoteUsd}\n recipientAddress={effectiveRecipientAddress}\n sourceRouteMessage={insufficientSourceIssue?.message}\n sourceRouteStatus={\n insufficientSourceIssue\n ? \"insufficient\"\n : isExactOutRouteLoading\n ? \"loading\"\n : undefined\n }\n swapType={swapType}\n toToken={toTokenWithFetchedBalance}\n totalBalance={totalSwapBalanceUsd}\n usdValue={amount && usdValue > 0 ? usdValue.toFixed(2) : \"\"}\n />\n\n {receiveAmountIssue && (\n \n )}\n\n {configuredAmountIssue && (\n \n )}\n\n {txError && !blockingQuoteIssue && (\n \n )}\n\n {/* CTA Button */}\n \n {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n void handleEnterPreview();\n }}\n style={{\n alignItems: \"center\",\n backgroundColor: blockingQuoteIssue\n ? \"var(--nexus-widget-error-background, #FCEEED)\"\n : isSwapCtaDisabled\n ? theme.colors.surfaceCool\n : primaryButtonBackground,\n border: blockingQuoteIssue\n ? \"1px solid var(--nexus-widget-error-border, #F7C4C1)\"\n : \"none\",\n borderRadius: theme.radius.primaryButton,\n boxShadow:\n blockingQuoteIssue || isSwapCtaDisabled\n ? \"none\"\n : theme.shadows.primaryButton,\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n gap: \"7px\",\n height: \"42px\",\n justifyContent: \"center\",\n marginTop: \"8px\",\n paddingInline: \"16px\",\n cursor: isSwapCtaDisabled ? \"default\" : \"pointer\",\n width: \"100%\",\n }}\n >\n {blockingQuoteIssue ? (\n \n ) : (needsWalletConnection && walletConnectBusy) ||\n quoteRefreshing ||\n receiveMaxCalculating ? (\n \n ) : null}\n \n {needsWalletConnection\n ? walletCtaLabel\n : fromTokens.length === 0\n ? \"Add Assets to Bridge\"\n : quoteCtaLabel(\"Review swap\")}\n \n \n \n \n )}\n\n {/* =============================================================== */}\n {/* DEPOSIT MODE LAYOUT */}\n {/* =============================================================== */}\n {activeMode === \"deposit\" &&\n [\n \"idle\",\n \"choose-swap-asset\",\n \"choose-receive-asset\",\n \"enter-recipient\",\n ].includes(swapStep) && (\n <>\n {isDepositMethodScreen && (\n \n setDepositFundingStep(\"onramp\")\n }\n onSelectWallet={() => setDepositFundingStep(\"wallet\")}\n primaryButtonForeground={primaryButtonForeground}\n totalBalance={totalSwapBalanceUsd}\n />\n )}\n\n {isDepositOnrampScreen && (\n {\n setTxError(message);\n onError?.(message);\n }}\n onSelectDestinationToken={(token) => {\n const tokenChanged = !isSameTokenSelection(\n toToken,\n token,\n );\n if (tokenChanged) {\n onReceiveAssetChange?.({\n chainId: token.chainId,\n chainName: token.chainName,\n contractAddress: token.contractAddress,\n symbol: token.symbol,\n });\n }\n const nextDeposit = getDepositForTokenSelection(\n configuredDepositOptions,\n token,\n );\n if (nextDeposit) {\n setSelectedOpportunity(nextDeposit);\n }\n setToToken(token);\n }}\n onSessionStateChange={setDepositOnrampSessionState}\n onSessionUpdate={recordOnrampSession}\n nexusSDK={nexusSDK}\n ownerAddress={ownerAddress}\n opportunity={selectedOpportunity}\n primaryButtonForeground={primaryButtonForeground}\n toToken={toTokenWithFetchedBalance}\n walletClient={walletClient}\n />\n )}\n\n {selectedOpportunity && depositFundingStep === \"wallet\" && (\n <>\n {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n captureSourceSelectionRequiredUsd();\n beginSourcePickerEdit();\n openDrawerStep(\"choose-swap-asset\");\n }}\n onOpenTokenPicker={() =>\n openDrawerStep(\"choose-receive-asset\")\n }\n onSetPercent={handleDepositPercentSelect}\n routeMessage={insufficientSourceIssue?.message}\n routeStatus={\n insufficientSourceIssue\n ? \"insufficient\"\n : displayExactOutRouteLoading\n ? \"loading\"\n : undefined\n }\n showAutoBadge={!sourceSelectionTouched}\n isTokenPickerDisabled={isReceiveAssetPickerLocked}\n hideDestinationTokenDropdownIcon={\n hideDestinationTokenDropdownIcon\n }\n tokenValue={depositTokenDisplay}\n toToken={toTokenWithFetchedBalance}\n totalBalance={totalSwapBalanceUsd}\n usdValue={depositUsdDisplay}\n />\n\n {receiveAmountIssue && (\n \n )}\n\n {configuredAmountIssue && (\n \n )}\n\n {txError && !blockingQuoteIssue && (\n \n )}\n\n \n {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n void handleEnterPreview();\n }}\n style={{\n alignItems: \"center\",\n backgroundColor: blockingQuoteIssue\n ? \"var(--nexus-widget-error-background, #FCEEED)\"\n : isDepositCtaDisabled\n ? theme.colors.surfaceCool\n : primaryButtonBackground,\n border: blockingQuoteIssue\n ? \"1px solid var(--nexus-widget-error-border, #F7C4C1)\"\n : \"none\",\n borderRadius: blockingQuoteIssue\n ? \"4px\"\n : theme.radius.primaryButton,\n boxShadow:\n blockingQuoteIssue || isDepositCtaDisabled\n ? \"none\"\n : theme.shadows.primaryButton,\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n gap: \"7px\",\n height: \"40px\",\n justifyContent: \"center\",\n paddingInline: \"16px\",\n cursor: isDepositCtaDisabled ? \"default\" : \"pointer\",\n width: \"100%\",\n }}\n >\n {blockingQuoteIssue ? (\n \n ) : (needsWalletConnection && walletConnectBusy) ||\n isExactOutPaymentQuotePending ||\n receiveMaxCalculating ? (\n \n ) : null}\n \n {quoteCtaLabel(\"Review deposit\")}\n \n \n \n \n )}\n \n )}\n\n {/* =============================================================== */}\n {/* SEND MODE — recipient first, then amount, then asset */}\n {/* =============================================================== */}\n {activeMode === \"send\" &&\n [\n \"idle\",\n \"choose-swap-asset\",\n \"choose-receive-asset\",\n \"enter-recipient\",\n ].includes(swapStep) && (\n <>\n \n openDrawerStep(\"choose-receive-asset\")\n }\n isRecipientLocked={isConfiguredRecipientLocked}\n onOpenRecipientPicker={\n isConfiguredRecipientLocked\n ? () => undefined\n : handleOpenRecipientEditor\n }\n onOpenSourcePicker={() => {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n setEditingAssetIndex(null);\n captureSourceSelectionRequiredUsd();\n beginSourcePickerEdit();\n openDrawerStep(\"choose-swap-asset\");\n }}\n onSetPercent={handleSendPercentSelect}\n recipientAddress={recipientAddress || \"\"}\n routeMessage={insufficientSourceIssue?.message}\n routeStatus={\n insufficientSourceIssue\n ? \"insufficient\"\n : displayExactOutRouteLoading\n ? \"loading\"\n : undefined\n }\n showAutoBadge={!sourceSelectionTouched}\n toToken={toTokenWithFetchedBalance}\n totalBalance={totalSwapBalanceUsd}\n usdValue={\n amount && sendAmountUsd > 0 ? sendAmountUsd.toFixed(2) : \"\"\n }\n />\n\n {receiveAmountIssue && (\n \n )}\n\n {configuredAmountIssue && (\n \n )}\n\n {txError && !blockingQuoteIssue && (\n \n )}\n\n \n {\n if (needsWalletConnection) {\n void handleConnectWallet();\n return;\n }\n if (sendNeedsRecipient) {\n handleOpenRecipientEditor();\n return;\n }\n void handleEnterPreview();\n }}\n style={{\n alignItems: \"center\",\n backgroundColor: blockingQuoteIssue\n ? \"var(--nexus-widget-error-background, #FCEEED)\"\n : isSendCtaDisabled\n ? theme.colors.surfaceCool\n : primaryButtonBackground,\n border: blockingQuoteIssue\n ? \"1px solid var(--nexus-widget-error-border, #F7C4C1)\"\n : \"none\",\n borderRadius: blockingQuoteIssue\n ? \"4px\"\n : theme.radius.primaryButton,\n boxShadow:\n blockingQuoteIssue || isSendCtaDisabled\n ? \"none\"\n : theme.shadows.primaryButton,\n boxSizing: \"border-box\",\n display: \"flex\",\n flexShrink: 0,\n gap: \"7px\",\n height: \"40px\",\n justifyContent: \"center\",\n paddingInline: \"16px\",\n cursor: isSendCtaDisabled ? \"default\" : \"pointer\",\n width: \"100%\",\n }}\n >\n {blockingQuoteIssue ? (\n \n ) : (needsWalletConnection && walletConnectBusy) ||\n (!sendNeedsRecipient &&\n (isExactOutPaymentQuotePending ||\n receiveMaxCalculating)) ? (\n \n ) : null}\n \n {sendCtaLabel}\n \n \n \n \n )}\n \n \n\n {/* ================================================================== */}\n {/* DRAWER PANELS — rendered as direct children of root widget */}\n {/* so they overlay the main page as bottom drawers */}\n {/* ================================================================== */}\n\n {/* Drawer: enter-recipient */}\n {(activeMode === \"swap\" ||\n activeMode === \"send\" ||\n activeMode === \"deposit\") &&\n swapStep === \"enter-recipient\" && (\n \n {\n setTxError(null);\n closeDrawerToIdle();\n }}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: \"rgba(0,0,0,0.35)\",\n pointerEvents: \"auto\",\n opacity: isRecipientDrawerClosing ? 0 : 1,\n transition: `opacity ${DRAWER_CLOSE_MS}ms ease`,\n }}\n />\n \n \n \n \n \n {\n setTxError(null);\n closeDrawerToIdle();\n }}\n style={{\n alignItems: \"center\",\n backgroundColor:\n \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n border: `1px solid ${theme.colors.border}`,\n borderRadius: \"8px\",\n cursor: \"pointer\",\n display: \"flex\",\n flexShrink: 0,\n height: \"32px\",\n justifyContent: \"center\",\n padding: 0,\n width: \"32px\",\n }}\n type=\"button\"\n >\n \n \n \n Recipient\n \n \n \n \n \n Wallet Address\n \n {activeMode === \"swap\" && defaultRecipientAddress && (\n \n Reset to default\n \n )}\n \n {\n setRecipientAddress(next);\n if (txError) setTxError(null);\n }}\n onClear={() => setRecipientAddress(\"\")}\n placeholder=\"Wallet address\"\n value={recipientAddress}\n />\n {txError && (\n \n {txError}\n \n )}\n {activeMode === \"send\" && (\n \n Recipient must be different from the connected wallet.\n \n )}\n \n Save\n \n \n \n )}\n\n {/* Drawer: choose-swap-asset */}\n {(activeMode === \"swap\" ||\n activeMode === \"send\" ||\n activeMode === \"deposit\") &&\n swapStep === \"choose-swap-asset\" && (\n \n \n \n {\n if (activeMode === \"swap\") {\n const next = [...fromTokens];\n const targetIndex =\n editingAssetIndex !== null &&\n editingAssetIndex < next.length\n ? editingAssetIndex\n : null;\n const existingToken =\n targetIndex !== null ? next[targetIndex] : undefined;\n const tokenChanged = !isSameTokenSelection(\n existingToken,\n token,\n );\n const preservedAmount = tokenChanged\n ? \"\"\n : existingToken?.userAmount ||\n (targetIndex === 0 ? amount : \"\");\n const newToken = {\n ...token,\n userAmount: preservedAmount,\n };\n\n if (targetIndex !== null) {\n next[targetIndex] = newToken;\n } else {\n next.push(newToken);\n }\n\n if (tokenChanged) {\n clearPendingSwapIntent();\n setAmount(getSourceAmountInput(next));\n }\n if (swapType !== \"exactIn\") {\n setSwapType(\"exactIn\");\n }\n setFromTokens(next);\n closeDrawerToIdle();\n } else if (\n activeMode === \"deposit\" ||\n activeMode === \"send\"\n ) {\n handleSourcePickerDraftSelectionChange([\n { ...token, userAmount: \"\" },\n ]);\n }\n }}\n onSelectionChange={\n activeMode === \"deposit\" || activeMode === \"send\"\n ? handleSourcePickerDraftSelectionChange\n : undefined\n }\n onToggle={(token) => {\n const isDepositOrSendSourcePicker =\n activeMode === \"deposit\" || activeMode === \"send\";\n const prevTokens = isDepositOrSendSourcePicker\n ? sourcePickerSelectedTokens\n : fromTokens;\n const isSameSelection = (\n a: SwapTokenOption,\n b: SwapTokenOption,\n ) => {\n if (a.isUnified || b.isUnified) {\n return Boolean(\n a.isUnified &&\n b.isUnified &&\n a.unifiedSymbol === b.unifiedSymbol,\n );\n }\n return (\n a.contractAddress.toLowerCase() ===\n b.contractAddress.toLowerCase() &&\n a.chainId === b.chainId\n );\n };\n const sourceTokens = token.sourceTokens ?? [];\n const isSameUnifiedGroup = (item: SwapTokenOption) =>\n Boolean(\n item.isUnified &&\n token.isUnified &&\n item.unifiedSymbol === token.unifiedSymbol,\n );\n const withDefaultAmount = (item: SwapTokenOption) => ({\n ...item,\n userAmount:\n activeMode === \"swap\" && prevTokens.length === 0\n ? amount\n : \"\",\n });\n const getNextTokens = () => {\n if (\n isDepositOrSendSourcePicker &&\n token.isUnified &&\n sourceTokens.length > 0\n ) {\n const hasUnifiedSelection =\n prevTokens.some(isSameUnifiedGroup);\n const areAllChildrenSelected = sourceTokens.every(\n (source) =>\n prevTokens.some((item) =>\n isSameSelection(item, source),\n ),\n );\n const withoutGroup = prevTokens.filter(\n (item) =>\n !isSameUnifiedGroup(item) &&\n !sourceTokens.some((source) =>\n isSameSelection(item, source),\n ),\n );\n\n if (hasUnifiedSelection || areAllChildrenSelected) {\n return withoutGroup;\n }\n\n return [\n ...withoutGroup,\n ...sourceTokens.map((source) =>\n withDefaultAmount(source),\n ),\n ];\n }\n\n if (isDepositOrSendSourcePicker && !token.isUnified) {\n const unifiedSelection = prevTokens.find(\n (item) =>\n item.isUnified &&\n item.sourceTokens?.some((source) =>\n isSameSelection(source, token),\n ),\n );\n\n if (unifiedSelection?.sourceTokens?.length) {\n const withoutUnified = prevTokens.filter(\n (item) => !isSameSelection(item, unifiedSelection),\n );\n return [\n ...withoutUnified,\n ...unifiedSelection.sourceTokens\n .filter((source) => !isSameSelection(source, token))\n .map((source) => withDefaultAmount(source)),\n ];\n }\n }\n\n const exists = prevTokens.find((item) =>\n isSameSelection(item, token),\n );\n if (exists) {\n return prevTokens.filter(\n (item) => !isSameSelection(item, token),\n );\n }\n const tokenSourceKeys = new Set(\n (token.sourceTokens ?? []).map(\n (source) =>\n `${source.chainId}-${source.contractAddress.toLowerCase()}`,\n ),\n );\n const next = prevTokens.filter((existing) => {\n if (\n token.isUnified &&\n tokenSourceKeys.has(\n `${existing.chainId}-${existing.contractAddress.toLowerCase()}`,\n )\n ) {\n return false;\n }\n if (\n existing.isUnified &&\n existing.sourceTokens?.some(\n (source) =>\n source.chainId === token.chainId &&\n source.contractAddress.toLowerCase() ===\n token.contractAddress.toLowerCase(),\n )\n ) {\n return false;\n }\n return true;\n });\n return [...next, withDefaultAmount(token)];\n };\n const nextTokens = getNextTokens();\n\n if (isDepositOrSendSourcePicker) {\n handleSourcePickerDraftSelectionChange(nextTokens);\n } else {\n clearPendingSwapIntent();\n setFromTokens(nextTokens);\n }\n }}\n preserveSelectedBelowMinimum={false}\n requiredUsd={assetSelectorRequiredUsdDisplay}\n selectedTokens={sourcePickerSelectedTokens}\n showBelowMinimumInline={\n activeMode === \"swap\" && swapType === \"exactIn\"\n }\n swapBalance={swapBalance}\n swapSupportedChains={swapSupportedChainsAndTokens}\n title={\n activeMode === \"deposit\" || activeMode === \"send\"\n ? \"Choose Assets to Pay with\"\n : \"Choose assets to send\"\n }\n />\n \n \n )}\n\n {/* Drawer: choose-receive-asset */}\n {(activeMode === \"swap\" ||\n activeMode === \"send\" ||\n activeMode === \"deposit\") &&\n swapStep === \"choose-receive-asset\" && (\n \n \n \n {\n const tokenChanged = !isSameTokenSelection(toToken, token);\n if (tokenChanged) {\n onReceiveAssetChange?.({\n chainId: token.chainId,\n chainName: token.chainName,\n contractAddress: token.contractAddress,\n symbol: token.symbol,\n });\n }\n if (activeMode === \"send\" || activeMode === \"deposit\") {\n setExactOutQuoteSourceModeValue(\"all\");\n if (tokenChanged) {\n clearPendingSwapIntent();\n if (!isConfiguredAmountFixed) {\n setAmount(\"\");\n }\n }\n setSwapType(\"exactOut\");\n if (activeMode === \"deposit\") {\n const nextDeposit = getDepositForTokenSelection(\n configuredDepositOptions,\n token,\n );\n if (nextDeposit) {\n setSelectedOpportunity(nextDeposit);\n }\n }\n setToToken(token);\n closeDrawerToIdle();\n return;\n }\n if (tokenChanged) {\n clearPendingSwapIntent();\n }\n if (swapType !== \"exactIn\") {\n setSwapType(\"exactIn\");\n }\n setToToken(token);\n closeDrawerToIdle();\n }}\n />\n \n \n )}\n \n );\n\n if (embed) return widgetContent;\n\n return (\n \n \n \n \n \n {widgetContent}\n \n \n );\n}\n\nexport default NexusWidget;\n", "type": "registry:component", "target": "components/nexus/nexus.tsx" }, @@ -116,13 +134,13 @@ }, { "path": "registry/avail-widgets/nexus-widget/theme.ts", - "content": "import type { CSSProperties } from \"react\";\nimport type { NexusWidgetTheme } from \"./types\";\n\n/** Paper dark palette. Light values remain at each existing color use site. */\nexport const nexusWidgetDarkColors = {\n \"--nexus-widget-text-strong\": \"#EDEDEC\",\n \"--nexus-widget-text\": \"#EDEDEC\",\n \"--nexus-widget-text-secondary\": \"#A1A1A0\",\n \"--nexus-widget-text-tertiary\": \"#878786\",\n \"--nexus-widget-text-disabled\": \"#5B5B5A\",\n \"--nexus-widget-surface\": \"#1A1A18\",\n \"--nexus-widget-surface-raised\": \"#292928\",\n \"--nexus-widget-surface-hover\": \"#2E2E2D\",\n \"--nexus-widget-surface-pressed\": \"#1F1F1E\",\n \"--nexus-widget-surface-active\": \"#454544\",\n \"--nexus-widget-surface-inset\": \"#111110\",\n \"--nexus-widget-background\": \"#0E0E0D\",\n \"--nexus-widget-border\": \"#2E2E2D\",\n \"--nexus-widget-border-control\": \"#2E2E2D\",\n \"--nexus-widget-border-empty\": \"#454544\",\n \"--nexus-widget-border-unchecked\": \"#A1A1A0\",\n \"--nexus-widget-error-background\": \"#541010\",\n \"--nexus-widget-error-text\": \"#FBE9E9\",\n \"--nexus-widget-error-border\": \"#541010\",\n \"--nexus-widget-error-accent\": \"#D43A3A\",\n \"--nexus-widget-warning-background\": \"#4A2A00\",\n \"--nexus-widget-warning-text\": \"#FEF3D8\",\n \"--nexus-widget-success-background\": \"#0C5626\",\n \"--nexus-widget-success-text\": \"#A5EFBF\",\n \"--nexus-widget-shadow-soft\": \"#00000040\",\n \"--nexus-widget-shadow-medium\": \"#00000059\",\n \"--nexus-widget-shadow-strong\": \"#00000073\",\n \"--nexus-widget-shadow-inset\": \"#00000040\",\n \"--nexus-widget-shadow-highlight\": \"#FFFFFF00\",\n \"--nexus-widget-root-shadow\":\n \"0 0 0 1px var(--nexus-widget-border), 0 12px 32px var(--nexus-widget-shadow-medium)\",\n \"--nexus-widget-overlay\": \"rgba(0,0,0,0.46)\",\n \"--nexus-widget-skeleton-highlight\": \"#454544\",\n \"--nexus-widget-focus-border\": \"var(--nexus-widget-primary)\",\n \"--nexus-widget-focus-ring\": \"color-mix(in srgb, var(--nexus-widget-primary) 16%, transparent)\",\n \"--nexus-widget-primary-soft\": \"#292928\",\n \"--nexus-widget-primary-soft-text\": \"#EDEDEC\",\n \"--nexus-widget-button-background\": \"var(--nexus-widget-primary)\",\n \"--nexus-widget-button-foreground\": \"var(--nexus-widget-primary-foreground)\",\n \"--nexus-widget-background-image\": \"none\",\n} as const;\n\n/** Interaction colors only: the existing dimensions and event handlers stay intact. */\nexport const nexusWidgetInteractionStyles = `\n [data-nexus-widget-theme=\"dark\"] input::placeholder {\n color: var(--nexus-widget-text-tertiary);\n -webkit-text-fill-color: var(--nexus-widget-text-tertiary);\n }\n [data-nexus-widget-percent-theme=\"dark\"] {\n background-color: var(--nexus-widget-surface-raised) !important;\n color: var(--nexus-widget-text-secondary) !important;\n }\n [data-nexus-widget-percent-theme=\"dark\"]:hover {\n background-color: var(--nexus-widget-surface-hover) !important;\n color: var(--nexus-widget-text) !important;\n }\n [data-nexus-widget-percent-theme=\"dark\"][data-selected=\"true\"] {\n background-color: var(--nexus-widget-surface-active) !important;\n color: var(--nexus-widget-text) !important;\n }\n [data-nexus-widget-percent-theme=\"dark\"]:active {\n background-color: var(--nexus-widget-surface-pressed) !important;\n color: var(--nexus-widget-text) !important;\n }\n [data-nexus-widget-percent-theme=\"dark\"]:disabled,\n [data-nexus-widget-percent-theme=\"dark\"][data-disabled=\"true\"] {\n background-color: var(--nexus-widget-surface-raised) !important;\n color: var(--nexus-widget-text-disabled) !important;\n }\n`;\n\n/** Reset every token in light mode so nested widgets cannot inherit dark colors. */\nexport function getNexusWidgetThemeStyle(isDark: boolean): CSSProperties {\n return {\n ...Object.fromEntries(\n Object.entries(nexusWidgetDarkColors).map(([name, value]) => [\n name,\n isDark ? value : \"initial\",\n ])\n ),\n colorScheme: isDark ? \"dark\" : \"light\",\n } as CSSProperties;\n}\n\nexport function resolveNexusWidgetTheme(\n theme: NexusWidgetTheme | undefined,\n legacyMode?: NexusWidgetTheme\n): NexusWidgetTheme {\n const mode = theme ?? legacyMode;\n return mode === \"dark\" || mode === \"system\" ? mode : \"light\";\n}\n\nconst ink = {\n 900: \"var(--nexus-widget-text-strong, #161615)\",\n 800: \"var(--nexus-widget-text, #1F1F1F)\",\n 600: \"var(--nexus-widget-text-secondary, #5B5B5A)\",\n 500: \"var(--nexus-widget-text-secondary, #848483)\",\n 400: \"var(--nexus-widget-text-secondary, #8E8E89)\",\n 300: \"var(--nexus-widget-text-tertiary, #C9C9C5)\",\n} as const;\n\nexport const NEXUS_WIDGET_DEFAULT_PRIMARY_COLOR = \"rgb(0, 107, 244)\" as const;\n\nconst blue = {\n 700: \"var(--foreground-brand)\",\n 500: \"var(--foreground-brand)\",\n 100: \"var(--nexus-widget-primary-soft, #EAF1FF)\",\n 50: \"var(--nexus-widget-primary-soft, #E5EEFF)\",\n tab: \"var(--nexus-widget-surface-raised, #F0F3F9)\",\n} as const;\n\nconst surface = {\n default: \"var(--nexus-widget-surface, #FFFFFE)\",\n soft: \"var(--nexus-widget-surface-inset, #FAFAFC)\",\n cool: \"var(--nexus-widget-surface-raised, #F6F6F6)\",\n border: \"var(--nexus-widget-border, #ECECEA)\",\n border2: \"var(--nexus-widget-border, #E8E8E7)\",\n} as const;\n\nconst status = {\n success: \"var(--nexus-widget-success-text, #1BC57A)\",\n successBg: \"var(--nexus-widget-success-background, rgba(27, 197, 122, 0.18))\",\n} as const;\n\nexport const nexusWidgetTheme = {\n colors: {\n ink,\n blue,\n surfaceScale: surface,\n status,\n\n background: surface.default,\n border: surface.border2,\n divider: surface.border,\n icon: ink[600],\n muted: ink[400],\n primary: blue[700],\n primaryText: blue[500],\n segmented: blue.tab,\n surface: surface.default,\n surfaceCool: surface.cool,\n surfaceInset: surface.soft,\n text: ink[800],\n textEmpty: ink[300],\n textStrong: ink[900],\n textSubtle: ink[500],\n },\n fonts: {\n display: '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n mono: '\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace',\n sans: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n },\n typography: {\n displayXl: {\n fontFamily: '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"31px\",\n fontWeight: 500,\n letterSpacing: \"0\",\n lineHeight: \"36px\",\n },\n displayLg: {\n fontFamily: '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"22px\",\n fontWeight: 500,\n letterSpacing: \"0\",\n lineHeight: \"26px\",\n },\n headingPanel: {\n fontFamily: '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"17px\",\n fontWeight: 500,\n letterSpacing: \"0\",\n lineHeight: \"21px\",\n },\n bodyLg: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"14px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"17px\",\n },\n bodyMd: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"14px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"20px\",\n },\n bodySm: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"13px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"17px\",\n },\n labelCap: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"11px\",\n fontWeight: 500,\n letterSpacing: \"0.08em\",\n lineHeight: \"14px\",\n textTransform: \"uppercase\",\n },\n caption: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"11px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"15px\",\n },\n code: {\n fontFamily:\n '\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: \"11px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"14px\",\n },\n },\n radius: {\n modal: \"16px\",\n panel: \"9px\",\n primaryButton: \"10px\",\n segmented: \"7px\",\n segmentedItem: \"5px\",\n tokenPill: \"999px\",\n iconButton: \"999px\",\n },\n shadows: {\n card: \"var(--nexus-widget-shadow-medium, #3C286433) 0px 0px 3px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 1px 4px\",\n control: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 6px\",\n iconButton: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 4px\",\n inset: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px inset\",\n primaryButton:\n \"var(--nexus-widget-shadow-highlight, #FFFFFF12) 0px 1px 0px inset, var(--nexus-widget-shadow-strong, #0000001F) 0px 1px 2px, var(--nexus-widget-shadow-medium, #14141E24) 0px 4px 10px\",\n root: \"var(--nexus-widget-shadow-highlight, #FFFFFFE6) 0px 1px 0px inset, var(--nexus-widget-shadow-highlight, #FFFFFF8C) 0px 0px 0px 9px, var(--nexus-widget-shadow-soft, #11346A0A) 0px 2px 4px, var(--nexus-widget-shadow-soft, #0078F721) 0px 9px 18px, var(--nexus-widget-shadow-soft, #1571FE1F) 0px 22px 42px\",\n segmentedActive:\n \"var(--nexus-widget-shadow-highlight, #FFFFFFE6) 0px 1px 0px inset, var(--nexus-widget-shadow-soft, #3C286414) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640F) 0px 2px 6px\",\n sheet: \"var(--nexus-widget-shadow-strong, #0000001F) 0px -4px 20px\",\n tokenPill: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 8px\",\n tooltip: \"0 8px 24px var(--nexus-widget-shadow-strong, rgba(22,22,21,0.12))\",\n },\n primitives: {\n badge: {\n backgroundColor: blue[100],\n color: blue[500],\n },\n iconButton: {\n backgroundColor: surface.default,\n borderColor: \"var(--nexus-widget-border-control, #0000000F)\",\n boxShadow: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 4px\",\n size: \"29px\",\n },\n tokenPill: {\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderColor: \"var(--nexus-widget-border-control, #0000000A)\",\n boxShadow: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 8px\",\n },\n },\n} as const;\n", + "content": "import type { CSSProperties } from \"react\";\nimport type { NexusWidgetTheme } from \"./types\";\n\n/** Paper dark palette. Light values remain at each existing color use site. */\nexport const nexusWidgetDarkColors = {\n \"--nexus-widget-text-strong\": \"#EDEDEC\",\n \"--nexus-widget-text\": \"#EDEDEC\",\n \"--nexus-widget-text-secondary\": \"#A1A1A0\",\n \"--nexus-widget-text-tertiary\": \"#878786\",\n \"--nexus-widget-text-disabled\": \"#5B5B5A\",\n \"--nexus-widget-surface\": \"#1A1A18\",\n \"--nexus-widget-surface-raised\": \"#292928\",\n \"--nexus-widget-surface-hover\": \"#2E2E2D\",\n \"--nexus-widget-surface-pressed\": \"#1F1F1E\",\n \"--nexus-widget-surface-active\": \"#454544\",\n \"--nexus-widget-surface-inset\": \"#111110\",\n \"--nexus-widget-background\": \"#0E0E0D\",\n \"--nexus-widget-border\": \"#2E2E2D\",\n \"--nexus-widget-border-control\": \"#2E2E2D\",\n \"--nexus-widget-border-empty\": \"#454544\",\n \"--nexus-widget-border-unchecked\": \"#A1A1A0\",\n \"--nexus-widget-error-background\": \"#541010\",\n \"--nexus-widget-error-text\": \"#FBE9E9\",\n \"--nexus-widget-error-border\": \"#541010\",\n \"--nexus-widget-error-accent\": \"#D43A3A\",\n \"--nexus-widget-warning-background\": \"#4A2A00\",\n \"--nexus-widget-warning-text\": \"#FEF3D8\",\n \"--nexus-widget-success-background\": \"#0C5626\",\n \"--nexus-widget-success-text\": \"#A5EFBF\",\n \"--nexus-widget-shadow-soft\": \"#00000040\",\n \"--nexus-widget-shadow-medium\": \"#00000059\",\n \"--nexus-widget-shadow-strong\": \"#00000073\",\n \"--nexus-widget-shadow-inset\": \"#00000040\",\n \"--nexus-widget-shadow-highlight\": \"#FFFFFF00\",\n \"--nexus-widget-root-shadow\":\n \"0 0 0 1px var(--nexus-widget-border), 0 12px 32px var(--nexus-widget-shadow-medium)\",\n \"--nexus-widget-overlay\": \"rgba(0,0,0,0.46)\",\n \"--nexus-widget-skeleton-highlight\": \"#454544\",\n \"--nexus-widget-focus-border\": \"var(--nexus-widget-primary)\",\n \"--nexus-widget-focus-ring\": \"color-mix(in srgb, var(--nexus-widget-primary) 16%, transparent)\",\n \"--nexus-widget-primary-soft\": \"#292928\",\n \"--nexus-widget-primary-soft-text\": \"#EDEDEC\",\n \"--nexus-widget-button-background\": \"var(--nexus-widget-primary)\",\n \"--nexus-widget-button-foreground\": \"var(--nexus-widget-primary-foreground)\",\n \"--nexus-widget-background-image\": \"none\",\n} as const;\n\n/** Interaction colors only: the existing dimensions and event handlers stay intact. */\nexport const nexusWidgetInteractionStyles = `\n [data-nexus-widget-theme=\"dark\"] input::placeholder {\n color: var(--nexus-widget-text-tertiary);\n -webkit-text-fill-color: var(--nexus-widget-text-tertiary);\n }\n [data-nexus-widget-percent-theme=\"dark\"] {\n background-color: var(--nexus-widget-surface-raised) !important;\n color: var(--nexus-widget-text-secondary) !important;\n }\n [data-nexus-widget-percent-theme=\"dark\"]:hover {\n background-color: var(--nexus-widget-surface-hover) !important;\n color: var(--nexus-widget-text) !important;\n }\n [data-nexus-widget-percent-theme=\"dark\"][data-selected=\"true\"] {\n background-color: var(--nexus-widget-surface-active) !important;\n color: var(--nexus-widget-text) !important;\n }\n [data-nexus-widget-percent-theme=\"dark\"]:active {\n background-color: var(--nexus-widget-surface-pressed) !important;\n color: var(--nexus-widget-text) !important;\n }\n [data-nexus-widget-percent-theme=\"dark\"]:disabled,\n [data-nexus-widget-percent-theme=\"dark\"][data-disabled=\"true\"] {\n background-color: var(--nexus-widget-surface-raised) !important;\n color: var(--nexus-widget-text-disabled) !important;\n }\n`;\n\n/** Reset every token in light mode so nested widgets cannot inherit dark colors. */\nexport function getNexusWidgetThemeStyle(isDark: boolean): CSSProperties {\n return {\n ...Object.fromEntries(\n Object.entries(nexusWidgetDarkColors).map(([name, value]) => [\n name,\n isDark ? value : \"initial\",\n ])\n ),\n colorScheme: isDark ? \"dark\" : \"light\",\n } as CSSProperties;\n}\n\nexport function resolveNexusWidgetTheme(\n theme: NexusWidgetTheme | undefined,\n legacyMode?: NexusWidgetTheme\n): NexusWidgetTheme {\n const mode = theme ?? legacyMode;\n return mode === \"dark\" || mode === \"system\" ? mode : \"light\";\n}\n\nconst ink = {\n 900: \"var(--nexus-widget-text-strong, #161615)\",\n 800: \"var(--nexus-widget-text, #1F1F1F)\",\n 600: \"var(--nexus-widget-text-secondary, #5B5B5A)\",\n 500: \"var(--nexus-widget-text-secondary, #848483)\",\n 400: \"var(--nexus-widget-text-secondary, #8E8E89)\",\n 300: \"var(--nexus-widget-text-tertiary, #C9C9C5)\",\n} as const;\n\nexport const NEXUS_WIDGET_DEFAULT_PRIMARY_COLOR = \"rgb(0, 107, 244)\" as const;\nexport const NEXUS_WIDGET_FAST_SPINNER_STYLE = {\n animation: \"nexusWidgetSpin 700ms linear infinite\",\n} as const;\nexport const NEXUS_WIDGET_FAST_SPINNER_ANIMATION =\n \"nexusWidgetSpin 700ms linear infinite\" as const;\n\nconst blue = {\n 700: \"var(--foreground-brand)\",\n 500: \"var(--foreground-brand)\",\n 100: \"var(--nexus-widget-primary-soft, #EAF1FF)\",\n 50: \"var(--nexus-widget-primary-soft, #E5EEFF)\",\n tab: \"var(--nexus-widget-surface-raised, #F0F3F9)\",\n} as const;\n\nconst surface = {\n default: \"var(--nexus-widget-surface, #FFFFFE)\",\n soft: \"var(--nexus-widget-surface-inset, #FAFAFC)\",\n cool: \"var(--nexus-widget-surface-raised, #F6F6F6)\",\n border: \"var(--nexus-widget-border, #ECECEA)\",\n border2: \"var(--nexus-widget-border, #E8E8E7)\",\n} as const;\n\nconst status = {\n success: \"var(--nexus-widget-success-text, #1BC57A)\",\n successBg: \"var(--nexus-widget-success-background, rgba(27, 197, 122, 0.18))\",\n} as const;\n\nexport const nexusWidgetTheme = {\n colors: {\n ink,\n blue,\n surfaceScale: surface,\n status,\n\n background: surface.default,\n border: surface.border2,\n divider: surface.border,\n icon: ink[600],\n muted: ink[400],\n primary: blue[700],\n primaryText: blue[500],\n segmented: blue.tab,\n surface: surface.default,\n surfaceCool: surface.cool,\n surfaceInset: surface.soft,\n text: ink[800],\n textEmpty: ink[300],\n textStrong: ink[900],\n textSubtle: ink[500],\n },\n fonts: {\n display: '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n mono: '\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace',\n sans: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n },\n typography: {\n displayXl: {\n fontFamily: '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"31px\",\n fontWeight: 500,\n letterSpacing: \"0\",\n lineHeight: \"36px\",\n },\n displayLg: {\n fontFamily: '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"22px\",\n fontWeight: 500,\n letterSpacing: \"0\",\n lineHeight: \"26px\",\n },\n headingPanel: {\n fontFamily: '\"Delight-Medium\", \"Delight\", system-ui, sans-serif',\n fontSize: \"17px\",\n fontWeight: 500,\n letterSpacing: \"0\",\n lineHeight: \"21px\",\n },\n bodyLg: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"14px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"17px\",\n },\n bodyMd: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"14px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"20px\",\n },\n bodySm: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"13px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"17px\",\n },\n labelCap: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"11px\",\n fontWeight: 500,\n letterSpacing: \"0.08em\",\n lineHeight: \"14px\",\n textTransform: \"uppercase\",\n },\n caption: {\n fontFamily: '\"Geist\", var(--font-geist-sans), system-ui, sans-serif',\n fontSize: \"11px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"15px\",\n },\n code: {\n fontFamily:\n '\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: \"11px\",\n fontWeight: 400,\n letterSpacing: \"0\",\n lineHeight: \"14px\",\n },\n },\n radius: {\n modal: \"16px\",\n panel: \"9px\",\n primaryButton: \"10px\",\n segmented: \"7px\",\n segmentedItem: \"5px\",\n tokenPill: \"999px\",\n iconButton: \"999px\",\n },\n shadows: {\n card: \"var(--nexus-widget-shadow-medium, #3C286433) 0px 0px 3px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 1px 4px\",\n control: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 6px\",\n iconButton: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 4px\",\n inset: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px inset\",\n primaryButton:\n \"var(--nexus-widget-shadow-highlight, #FFFFFF12) 0px 1px 0px inset, var(--nexus-widget-shadow-strong, #0000001F) 0px 1px 2px, var(--nexus-widget-shadow-medium, #14141E24) 0px 4px 10px\",\n root: \"var(--nexus-widget-shadow-highlight, #FFFFFFE6) 0px 1px 0px inset, var(--nexus-widget-shadow-highlight, #FFFFFF8C) 0px 0px 0px 9px, var(--nexus-widget-shadow-soft, #11346A0A) 0px 2px 4px, var(--nexus-widget-shadow-soft, #0078F721) 0px 9px 18px, var(--nexus-widget-shadow-soft, #1571FE1F) 0px 22px 42px\",\n segmentedActive:\n \"var(--nexus-widget-shadow-highlight, #FFFFFFE6) 0px 1px 0px inset, var(--nexus-widget-shadow-soft, #3C286414) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640F) 0px 2px 6px\",\n sheet: \"var(--nexus-widget-shadow-strong, #0000001F) 0px -4px 20px\",\n tokenPill: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 8px\",\n tooltip: \"0 8px 24px var(--nexus-widget-shadow-strong, rgba(22,22,21,0.12))\",\n },\n primitives: {\n badge: {\n backgroundColor: blue[100],\n color: blue[500],\n },\n iconButton: {\n backgroundColor: surface.default,\n borderColor: \"var(--nexus-widget-border-control, #0000000F)\",\n boxShadow: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 4px\",\n size: \"29px\",\n },\n tokenPill: {\n backgroundColor: \"var(--nexus-widget-surface-raised, #FFFFFE)\",\n borderColor: \"var(--nexus-widget-border-control, #0000000A)\",\n boxShadow: \"var(--nexus-widget-shadow-soft, #3C28640F) 0px 1px 2px, var(--nexus-widget-shadow-soft, #3C28640A) 0px 2px 8px\",\n },\n },\n} as const;\n", "type": "registry:component", "target": "components/nexus/theme.ts" }, { "path": "registry/avail-widgets/nexus-widget/types.ts", - "content": "import type { Address } from \"viem\";\n\nexport type NexusWidgetMode = \"swap\" | \"send\" | \"deposit\";\nexport type NexusWidgetTheme = \"dark\" | \"light\" | \"system\";\nexport type NexusWidgetNumericString = string;\nexport type NexusWidgetUrlString = `http://${string}` | `https://${string}`;\n\n/** Exact In: user specifies the \"from\" amount. Exact Out: user specifies the \"to\" amount. */\nexport type SwapType = \"exactIn\" | \"exactOut\";\n\nexport type DepositExecuteConfig = {\n to: Address;\n value?: bigint;\n data?: `0x${string}`;\n gas: bigint;\n tokenApproval?: {\n toTokenAddress: Address;\n amount: bigint;\n spender: Address;\n };\n};\n\nexport interface NexusWidgetDepositOpportunityConfig {\n apy?: string;\n chainId: number;\n depositTargetLogo?: string;\n description?: string;\n estimatedTime?: string;\n executeDeposit: (\n tokenSymbol: string,\n tokenAddress: Address,\n amount: bigint,\n chainId: number,\n user: Address\n ) => DepositExecuteConfig;\n explorerUrl?: string;\n gasTokenSymbol?: string;\n label?: string;\n logo?: string;\n\n /** Optional labels used by Nexus Widget history/progress copy. */\n protocol?: string;\n subtitle?: string;\n title?: string;\n tokenAddress: Address;\n tokenDecimals: number;\n tokenLogo?: string;\n tokenSymbol: string;\n}\n\nexport type NexusWidgetDepositOpportunityMetadata = Omit<\n NexusWidgetDepositOpportunityConfig,\n \"executeDeposit\"\n>;\n\nexport interface NexusWidgetRuntimePrefill {\n amount?: string;\n chain?: number;\n destination?: {\n chain: number;\n decimals?: number;\n logo?: string;\n symbol?: string;\n token: Address;\n };\n recipient?: Address;\n source?: {\n chain: number;\n decimals?: number;\n logo?: string;\n symbol?: string;\n token: Address;\n };\n token?: Address;\n}\n\nexport interface NexusWidgetDestinationToken {\n address: Address;\n decimals: number;\n logo?: NexusWidgetUrlString | string;\n symbol: string;\n}\n\nexport interface NexusWidgetPrefillToken extends NexusWidgetDestinationToken {\n chain: number;\n}\n\nexport type NexusWidgetDestinationTokenList = [\n NexusWidgetDestinationToken,\n ...NexusWidgetDestinationToken[],\n];\n\nexport interface NexusWidgetConfiguredDestination {\n chain?: number;\n tokens?: NexusWidgetDestinationTokenList;\n}\n\nexport interface NexusWidgetDepositDestination {\n chain: number;\n tokens: NexusWidgetDestinationTokenList;\n}\n\nexport type NexusWidgetDestination =\n | NexusWidgetConfiguredDestination\n | NexusWidgetDepositDestination;\n\nexport interface NexusWidgetAmountPrefill {\n amount?: NexusWidgetNumericString;\n}\n\nexport interface NexusWidgetTokenPrefill {\n token?: NexusWidgetPrefillToken;\n}\n\nexport type NexusWidgetSendPrefill =\n NexusWidgetAmountPrefill & NexusWidgetTokenPrefill;\n\nexport type NexusWidgetSwapPrefill = NexusWidgetTokenPrefill;\n\nexport interface NexusWidgetValidation {\n maxAmount?: NexusWidgetNumericString;\n minAmount?: NexusWidgetNumericString;\n}\n\nexport interface NexusWidgetAppearance {\n appName?: string;\n appLogoURL?: NexusWidgetUrlString | string;\n heading?: string;\n primaryColor?: string;\n /** Legacy theme setting. Prefer config.theme. */\n mode?: NexusWidgetTheme;\n}\n\nexport interface NexusWidgetConfigBase {\n appearance?: NexusWidgetAppearance;\n /** Defaults to light. System follows live OS color-scheme changes. */\n theme?: NexusWidgetTheme;\n}\n\nexport interface NexusWidgetDepositConfig extends NexusWidgetConfigBase {\n depositAddress: Address;\n destination: NexusWidgetDepositDestination;\n executeDeposit: NexusWidgetDepositOpportunityConfig[\"executeDeposit\"];\n mode: \"deposit\";\n prefill?: NexusWidgetAmountPrefill;\n validation?: NexusWidgetValidation;\n}\n\nexport interface NexusWidgetSendConfig extends NexusWidgetConfigBase {\n destination?: NexusWidgetConfiguredDestination;\n mode: \"send\";\n prefill?: NexusWidgetSendPrefill;\n recipientAddress?: Address;\n validation?: NexusWidgetValidation;\n}\n\nexport interface NexusWidgetSwapConfig extends NexusWidgetConfigBase {\n destination?: NexusWidgetConfiguredDestination;\n mode: \"swap\";\n prefill?: NexusWidgetSwapPrefill;\n recipientAddress?: Address;\n}\n\nexport type NexusWidgetConfig =\n | NexusWidgetDepositConfig\n | NexusWidgetSendConfig\n | NexusWidgetSwapConfig;\n\nexport interface NexusWidgetProps {\n className?: string;\n config: NexusWidgetConfig;\n connectedAddress?: Address;\n defaultOpen?: boolean;\n embed?: boolean;\n onClose?: () => void;\n onComplete?: (explorerUrl?: string) => void;\n onConnectClick?: () => void | Promise;\n onConnectWallet?: () => void | Promise;\n onError?: (message: string) => void;\n onOpenChange?: (open: boolean) => void;\n onReceiveAssetChange?: (asset: any) => void;\n onStart?: () => void;\n open?: boolean;\n}\n", + "content": "import type { Address } from \"viem\";\n\nexport type NexusWidgetMode = \"swap\" | \"send\" | \"deposit\";\nexport type NexusWidgetTheme = \"dark\" | \"light\" | \"system\";\nexport type NexusWidgetNumericString = string;\nexport type NexusWidgetUrlString = `http://${string}` | `https://${string}`;\n\n/** Exact In: user specifies the \"from\" amount. Exact Out: user specifies the \"to\" amount. */\nexport type SwapType = \"exactIn\" | \"exactOut\";\n\nexport type DepositExecuteConfig = {\n to: Address;\n value?: bigint;\n data?: `0x${string}`;\n gas: bigint;\n tokenApproval?: {\n toTokenAddress: Address;\n amount: bigint;\n spender: Address;\n };\n};\n\nexport interface NexusWidgetDepositOpportunityConfig {\n apy?: string;\n chainId: number;\n depositTargetLogo?: string;\n description?: string;\n estimatedTime?: string;\n executeDeposit: (\n tokenSymbol: string,\n tokenAddress: Address,\n amount: bigint,\n chainId: number,\n user: Address\n ) => DepositExecuteConfig;\n explorerUrl?: string;\n gasTokenSymbol?: string;\n label?: string;\n logo?: string;\n\n /** Optional labels used by Nexus Widget history/progress copy. */\n protocol?: string;\n subtitle?: string;\n title?: string;\n tokenAddress: Address;\n tokenDecimals: number;\n tokenLogo?: string;\n tokenSymbol: string;\n}\n\nexport type NexusWidgetDepositOpportunityMetadata = Omit<\n NexusWidgetDepositOpportunityConfig,\n \"executeDeposit\"\n>;\n\nexport interface NexusWidgetRuntimePrefill {\n amount?: string;\n chain?: number;\n destination?: {\n chain: number;\n decimals?: number;\n logo?: string;\n symbol?: string;\n token: Address;\n };\n recipient?: Address;\n source?: {\n chain: number;\n decimals?: number;\n logo?: string;\n symbol?: string;\n token: Address;\n };\n token?: Address;\n}\n\nexport interface NexusWidgetDestinationToken {\n address: Address;\n decimals: number;\n logo?: NexusWidgetUrlString | string;\n symbol: string;\n}\n\nexport interface NexusWidgetPrefillToken extends NexusWidgetDestinationToken {\n chain: number;\n}\n\nexport type NexusWidgetDestinationTokenList = [\n NexusWidgetDestinationToken,\n ...NexusWidgetDestinationToken[],\n];\n\nexport interface NexusWidgetConfiguredDestination {\n chain?: number;\n tokens?: NexusWidgetDestinationTokenList;\n}\n\nexport interface NexusWidgetDepositDestination {\n chain: number;\n tokens: NexusWidgetDestinationTokenList;\n}\n\nexport type NexusWidgetDestination =\n | NexusWidgetConfiguredDestination\n | NexusWidgetDepositDestination;\n\nexport interface NexusWidgetAmountPrefill {\n amount?: NexusWidgetNumericString;\n}\n\nexport interface NexusWidgetTokenPrefill {\n token?: NexusWidgetPrefillToken;\n}\n\nexport type NexusWidgetSendPrefill =\n NexusWidgetAmountPrefill & NexusWidgetTokenPrefill;\n\nexport type NexusWidgetSwapPrefill = NexusWidgetTokenPrefill;\n\nexport interface NexusWidgetValidation {\n maxAmount?: NexusWidgetNumericString;\n minAmount?: NexusWidgetNumericString;\n}\n\nexport interface NexusWidgetAppearance {\n appName?: string;\n appLogoURL?: NexusWidgetUrlString | string;\n heading?: string;\n primaryColor?: string;\n /** Legacy theme setting. Prefer config.theme. */\n mode?: NexusWidgetTheme;\n}\n\nexport interface NexusWidgetConfigBase {\n appearance?: NexusWidgetAppearance;\n /** Defaults to light. System follows live OS color-scheme changes. */\n theme?: NexusWidgetTheme;\n}\n\nexport interface NexusWidgetDepositConfig extends NexusWidgetConfigBase {\n depositAddress: Address;\n destination: NexusWidgetDepositDestination;\n /** Show local currency funding alongside wallet funding. Defaults to false. */\n enableOnRamp?: boolean;\n executeDeposit: NexusWidgetDepositOpportunityConfig[\"executeDeposit\"];\n mode: \"deposit\";\n prefill?: NexusWidgetAmountPrefill;\n validation?: NexusWidgetValidation;\n}\n\nexport interface NexusWidgetSendConfig extends NexusWidgetConfigBase {\n destination?: NexusWidgetConfiguredDestination;\n mode: \"send\";\n prefill?: NexusWidgetSendPrefill;\n recipientAddress?: Address;\n validation?: NexusWidgetValidation;\n}\n\nexport interface NexusWidgetSwapConfig extends NexusWidgetConfigBase {\n destination?: NexusWidgetConfiguredDestination;\n mode: \"swap\";\n prefill?: NexusWidgetSwapPrefill;\n recipientAddress?: Address;\n}\n\nexport type NexusWidgetConfig =\n | NexusWidgetDepositConfig\n | NexusWidgetSendConfig\n | NexusWidgetSwapConfig;\n\nexport interface NexusWidgetProps {\n className?: string;\n config: NexusWidgetConfig;\n connectedAddress?: Address;\n defaultOpen?: boolean;\n embed?: boolean;\n onClose?: () => void;\n onComplete?: (explorerUrl?: string) => void;\n onConnectClick?: () => void | Promise;\n onConnectWallet?: () => void | Promise;\n onError?: (message: string) => void;\n onOpenChange?: (open: boolean) => void;\n onReceiveAssetChange?: (asset: any) => void;\n onStart?: () => void;\n open?: boolean;\n}\n", "type": "registry:component", "target": "components/nexus/types.ts" }, @@ -144,6 +162,30 @@ "type": "registry:component", "target": "components/nexus/utils/deposit-source-selection.ts" }, + { + "path": "registry/avail-widgets/nexus-widget/utils/onramp-history.ts", + "content": "import {\n getNormalizedOnrampState,\n isOnrampTerminalState,\n mergeOnrampSession,\n normalizeOnrampSession,\n type OnrampSessionResponse,\n} from \"./onramp-session\";\n\nexport type OnrampHistoryContext = {\n chainId?: number;\n tokenSymbol?: string;\n destinationAmount?: string;\n sourceAmount?: string;\n sourceCurrencyCode?: string;\n provider?: string;\n paymentMethodType?: string;\n};\n\nexport type OnrampHistoryUpdate = {\n ownerAddress: string;\n session: OnrampSessionResponse;\n context?: OnrampHistoryContext;\n};\n\nexport type OnrampHistoryEntry = {\n kind: \"onramp\";\n id: string;\n ownerAddress: string;\n createdAt: number;\n startedAt: number;\n session: Omit;\n context: OnrampHistoryContext;\n};\n\nexport const getOnrampHistoryStorageKey = (ownerAddress: string, baseUrl: string) =>\n `nexus-widget-onramp-history-v1:${encodeURIComponent(baseUrl)}:${ownerAddress.toLowerCase()}`;\n\nconst optionalText = (value: unknown) =>\n typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n\nconst sanitizeContext = (context?: OnrampHistoryContext): OnrampHistoryContext => ({\n chainId: Number.isSafeInteger(context?.chainId) && context!.chainId! > 0\n ? context!.chainId : undefined,\n tokenSymbol: optionalText(context?.tokenSymbol),\n destinationAmount: optionalText(context?.destinationAmount),\n sourceAmount: optionalText(context?.sourceAmount),\n sourceCurrencyCode: optionalText(context?.sourceCurrencyCode),\n provider: optionalText(context?.provider),\n paymentMethodType: optionalText(context?.paymentMethodType),\n});\n\nconst sanitizeSession = (session: OnrampSessionResponse) => {\n const { widgetUrl: _widgetUrl, fallbackWidgetUrl: _fallbackWidgetUrl, deposit: _deposit, ...safe } =\n normalizeOnrampSession(session);\n return safe;\n};\n\nexport const upsertOnrampHistory = (\n entries: OnrampHistoryEntry[],\n update: OnrampHistoryUpdate,\n now = Date.now(),\n): OnrampHistoryEntry[] => {\n const sessionId = optionalText(update.session.sessionId);\n const ownerAddress = update.ownerAddress.toLowerCase();\n if (!sessionId || !/^0x[\\da-f]{40}$/i.test(ownerAddress)) return entries;\n if (update.session.transaction?.walletAddress &&\n update.session.transaction.walletAddress.toLowerCase() !== ownerAddress) return entries;\n const id = `onramp:${sessionId}`;\n const previous = entries.find((entry) => entry.id === id);\n const incoming = sanitizeSession(update.session);\n const previousTime = Date.parse(previous?.session.updatedAt ?? \"\");\n const incomingTime = Date.parse(incoming.updatedAt ?? \"\");\n if (previous && (\n incomingTime < previousTime ||\n (incoming.state && isOnrampTerminalState(previous.session.state) &&\n !isOnrampTerminalState(incoming.state))\n )) return entries;\n const createdAt = previous?.createdAt || Date.parse(incoming.createdAt ?? \"\") || now;\n const context = sanitizeContext({ ...previous?.context, ...update.context });\n const session = mergeOnrampSession(previous?.session, incoming);\n session.state = getNormalizedOnrampState(session.state) || \"AWAITING_USER\";\n const entry: OnrampHistoryEntry = {\n kind: \"onramp\", id, ownerAddress, createdAt, startedAt: createdAt, context, session,\n };\n if (previous && JSON.stringify(previous) === JSON.stringify(entry)) return entries;\n return [entry, ...entries.filter((item) => item.id !== id)]\n .sort((a, b) => b.createdAt - a.createdAt);\n};\n\nexport const readOnrampHistory = (ownerAddress: string, baseUrl: string): OnrampHistoryEntry[] => {\n if (!ownerAddress || typeof window === \"undefined\") return [];\n try {\n const parsed: unknown = JSON.parse(window.localStorage.getItem(\n getOnrampHistoryStorageKey(ownerAddress, baseUrl),\n ) ?? \"[]\");\n if (!Array.isArray(parsed)) return [];\n let entries: OnrampHistoryEntry[] = [];\n for (const value of parsed) {\n try {\n if (value?.kind !== \"onramp\" || value.ownerAddress !== ownerAddress.toLowerCase() ||\n !Number.isFinite(value.createdAt) || value.createdAt <= 0) continue;\n entries = upsertOnrampHistory(entries, {\n ownerAddress, session: value.session, context: value.context,\n }, value.createdAt);\n } catch { /* Ignore one malformed stored entry without losing the rest. */ }\n }\n return entries;\n } catch { return []; }\n};\n\nexport const writeOnrampHistory = (\n ownerAddress: string,\n baseUrl: string,\n entries: OnrampHistoryEntry[],\n) => {\n if (!ownerAddress || typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(getOnrampHistoryStorageKey(ownerAddress, baseUrl), JSON.stringify(entries));\n } catch { /* In-memory history remains usable when storage is unavailable. */ }\n};\n", + "type": "registry:component", + "target": "components/nexus/utils/onramp-history.ts" + }, + { + "path": "registry/avail-widgets/nexus-widget/utils/onramp-session.ts", + "content": "/** Logs are scoped to onramp; stringify snapshots so DevTools cannot retain SDK/client objects. */\nexport const logOnramp = (step: string, details: unknown = {}) => {\n try {\n const seen = new WeakSet();\n const snapshot = JSON.stringify(details, (key, value) => {\n if (\n (key === \"token\" && typeof value === \"string\") ||\n /^(authorization|signature|privateKey|seed|email|phone|clientIpAddress|widgetUrl|fallbackWidgetUrl|serviceProviderWidgetUrl)$/i.test(\n key,\n )\n ) {\n return \"[redacted]\";\n }\n if (typeof value === \"bigint\") return value.toString();\n if (typeof value === \"function\") return undefined;\n if (value instanceof Error) {\n return { ...value, name: value.name, message: value.message };\n }\n if (value && typeof value === \"object\") {\n if (seen.has(value)) return \"[circular]\";\n seen.add(value);\n }\n return value;\n });\n console.log(`[Nexus Onramp] ${new Date().toISOString()} ${step}`, snapshot);\n } catch {\n console.log(`[Nexus Onramp] ${step} [unserializable details]`);\n }\n};\n\nexport type OnrampSessionResponse = {\n createdAt?: string;\n fallbackWidgetUrl?: string;\n paymentMethodType?: string;\n provider?: string;\n rawMeldStatus?: string;\n deposit?: { explorerUrl?: string; state?: string; txHash?: string };\n sessionId?: string;\n state?: string;\n transaction?: {\n id?: string;\n status?: string;\n destinationAmount?: string;\n destinationCurrencyCode?: string;\n sourceAmount?: string;\n sourceCurrencyCode?: string;\n txHash?: string;\n walletAddress?: string;\n chainId?: number;\n };\n updatedAt?: string;\n widgetUrl?: string;\n};\n\nexport const getNormalizedOnrampState = (state?: string | null) =>\n (state ?? \"\").trim().toUpperCase();\n\nexport const ONRAMP_CLIENT_HEADER = \"nexus-widgets\";\n\nexport const getOnrampBaseUrl = () =>\n ((typeof process !== \"undefined\" &&\n process.env.NEXT_PUBLIC_NEXUS_ONRAMP_BASE_URL?.trim()) ||\n \"https://nexus-v2.mainnet.avail.so/middleware\").replace(/\\/+$/, \"\");\n\nconst TERMINAL_STATES = new Set([\n \"SETTLED\",\n \"FAILED\",\n \"DECLINED\",\n \"CANCELLED\",\n \"REFUNDED\",\n \"AUTHORIZATION_EXPIRED\",\n \"EXPIRED\",\n]);\n\nexport const isOnrampTerminalState = (state?: string | null) =>\n TERMINAL_STATES.has(getNormalizedOnrampState(state));\n\n/** Middleware and Meld may encode the same EVM chain as 10, \"10\", \"0xa\", or \"EVM_10\". */\nconst normalizeOnrampChainId = (value: unknown): number | undefined => {\n if (value == null) return undefined;\n let chainId = typeof value === \"number\" ? value : Number.NaN;\n if (typeof value === \"string\") {\n const id = value.trim().replace(/^EVM_/i, \"\");\n if (/^(?:\\d+|0x[\\da-f]+)$/i.test(id)) chainId = Number(id);\n }\n // A supplied but unrecognized ID must not become an absent ID and bypass the chain check.\n if (!Number.isSafeInteger(chainId) || chainId <= 0) {\n throw new Error(\"The payment response contains an invalid chain ID.\");\n }\n return chainId;\n};\n\n/** Accept both the middleware session envelope and Meld's documented transaction envelope. */\nexport const normalizeOnrampSession = (\n payload: any,\n currentSessionId?: string,\n): OnrampSessionResponse => {\n const data = payload?.session ?? payload ?? {};\n const transaction = data.transaction;\n const crypto = transaction?.cryptoDetails;\n const amount = (value: unknown) =>\n value == null ? undefined : String(value);\n const text = (...values: unknown[]) =>\n values.find((value): value is string =>\n typeof value === \"string\" && value.trim().length > 0,\n )?.trim();\n return {\n sessionId:\n currentSessionId ?? data.sessionId ?? data.externalSessionId ?? data.id,\n state: getNormalizedOnrampState(\n transaction?.status ?? data.rawMeldStatus ?? data.status ?? data.state,\n ),\n rawMeldStatus: transaction?.status ?? data.rawMeldStatus ?? data.status,\n provider: text(transaction?.serviceProvider, data.provider, data.serviceProvider),\n paymentMethodType: text(transaction?.paymentMethodType, data.paymentMethodType),\n createdAt: data.createdAt ?? transaction?.createdAt,\n updatedAt: data.updatedAt ?? transaction?.updatedAt,\n widgetUrl: data.serviceProviderWidgetUrl ?? data.widgetUrl,\n fallbackWidgetUrl: data.fallbackWidgetUrl,\n // A payment response cannot certify a wallet-executed deposit.\n transaction: transaction\n ? {\n id: transaction.id,\n status: transaction.status,\n destinationAmount: amount(transaction.destinationAmount),\n destinationCurrencyCode: transaction.destinationCurrencyCode,\n sourceAmount: amount(transaction.sourceAmount),\n sourceCurrencyCode: transaction.sourceCurrencyCode,\n txHash: crypto?.blockchainTransactionId ?? transaction.txHash,\n walletAddress: crypto?.walletAddress ?? transaction.walletAddress,\n chainId: normalizeOnrampChainId(\n crypto?.chainId ?? transaction.chainId,\n ),\n }\n : undefined,\n };\n};\n\n/** A partial status response must not erase previously reported payment details. */\nexport const mergeOnrampSession = (\n current: OnrampSessionResponse | null | undefined,\n incoming: OnrampSessionResponse,\n): OnrampSessionResponse => {\n const defined = (value: T) => Object.fromEntries(\n Object.entries(value).filter(([, field]) => field != null && field !== \"\"),\n ) as Partial;\n const merged: OnrampSessionResponse = {\n ...current,\n ...defined(incoming),\n transaction: incoming.transaction\n ? { ...current?.transaction, ...defined(incoming.transaction) }\n : current?.transaction,\n };\n // Retained transaction status must not override a newer top-level status on the next normalization.\n if (incoming.state) {\n merged.rawMeldStatus = incoming.rawMeldStatus ?? incoming.state;\n if (merged.transaction) merged.transaction = { ...merged.transaction, status: incoming.state };\n }\n return merged;\n};\n\n/** Read-only refresh shared by history; never executes a wallet transaction. */\nexport const fetchOnrampSession = async (\n baseUrl: string,\n sessionId: string,\n signal: AbortSignal,\n): Promise => {\n const response = await fetch(\n `${baseUrl.replace(/\\/+$/, \"\")}/api/v1/onramp/sessions/${encodeURIComponent(sessionId)}`,\n {\n method: \"GET\",\n cache: \"no-store\",\n signal: AbortSignal.any([signal, AbortSignal.timeout(20_000)]),\n headers: { \"Content-Type\": \"application/json\", \"x-nexus-client\": ONRAMP_CLIENT_HEADER },\n },\n );\n if (!response.ok) throw new Error(`Unable to refresh payment status (${response.status}).`);\n return normalizeOnrampSession(await response.json(), sessionId);\n};\n\n/** One request at a time. Refresh hints coalesce; stop aborts the request and clears the timer. */\nexport const startOnrampPolling = ({\n fetchSession,\n onData,\n onError,\n intervalMs = 3000,\n}: {\n fetchSession: (signal: AbortSignal) => Promise;\n onData: (data: T) => boolean; // true stops polling\n onError: (error: unknown) => void;\n intervalMs?: number;\n}) => {\n let stopped = false;\n let inFlight = false;\n let timer: ReturnType | undefined;\n const controller = new AbortController();\n const stop = () => {\n stopped = true;\n clearTimeout(timer);\n controller.abort();\n };\n const refresh = async () => {\n if (stopped || inFlight) return;\n clearTimeout(timer);\n inFlight = true;\n try {\n const data = await fetchSession(controller.signal);\n if (!stopped && onData(data)) stop();\n } catch (error) {\n if (!stopped) onError(error);\n } finally {\n inFlight = false;\n if (!stopped) timer = setTimeout(refresh, intervalMs);\n }\n };\n void refresh();\n return { refresh, stop };\n};\n\nexport const onrampDelay = (ms: number, signal: AbortSignal) =>\n new Promise((resolve, reject) => {\n signal.throwIfAborted();\n const abort = () => {\n clearTimeout(timer);\n reject(signal.reason);\n };\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", abort);\n resolve();\n }, ms);\n signal.addEventListener(\"abort\", abort, { once: true });\n });\n\nexport const waitForOnrampReceipt = async (\n readReceipt: () => Promise<{ status?: string } | null>,\n signal: AbortSignal,\n { timeoutMs = 120_000, intervalMs = 2000 } = {},\n) => {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n signal.throwIfAborted();\n const receipt = await readReceipt();\n signal.throwIfAborted();\n if (receipt?.status === \"0x0\")\n throw new Error(\"Transaction reverted on chain.\");\n if (receipt?.status === \"0x1\") return receipt;\n await onrampDelay(intervalMs, signal);\n }\n throw new Error(\n \"Transaction confirmation is pending. Retry to check the same transaction; do not pay again.\",\n );\n};\n\n/** Spend only this purchase, even when the wallet already held tokens before the gas swap. */\nexport const getOnrampRemainingAmount = (\n received: bigint,\n before: bigint,\n after: bigint,\n) => {\n const spent = before > after ? before - after : BigInt(0);\n const remaining = received - spent;\n if (remaining <= BigInt(0) || after < remaining) {\n throw new Error(\n \"The onramp balance cannot cover the deposit after gas funding.\",\n );\n }\n return remaining;\n};\n", + "type": "registry:component", + "target": "components/nexus/utils/onramp-session.ts" + }, + { + "path": "registry/avail-widgets/nexus-widget/utils/use-onramp-history.ts", + "content": "import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n fetchOnrampSession,\n getOnrampBaseUrl,\n isOnrampTerminalState,\n logOnramp,\n startOnrampPolling,\n} from \"./onramp-session\";\nimport {\n getOnrampHistoryStorageKey,\n readOnrampHistory,\n upsertOnrampHistory,\n writeOnrampHistory,\n type OnrampHistoryUpdate,\n} from \"./onramp-history\";\n\nexport const useOnrampHistory = ({\n ownerAddress = \"\", active, baseUrl = getOnrampBaseUrl(),\n}: { ownerAddress?: string; active: boolean; baseUrl?: string }) => {\n const owner = ownerAddress.toLowerCase();\n const key = getOnrampHistoryStorageKey(owner, baseUrl);\n const [history, setHistory] = useState(() => ({ key, entries: readOnrampHistory(owner, baseUrl) }));\n const historyRef = useRef(history);\n const scopeRef = useRef({ key, owner, baseUrl });\n scopeRef.current = { key, owner, baseUrl };\n\n useEffect(() => {\n const load = () => {\n const next = { key, entries: readOnrampHistory(owner, baseUrl) };\n historyRef.current = next;\n setHistory(next);\n };\n if (historyRef.current.key !== key) load();\n const onStorage = (event: StorageEvent) => {\n if (event.key === key || event.key === null) load();\n };\n window.addEventListener(\"storage\", onStorage);\n return () => window.removeEventListener(\"storage\", onStorage);\n }, [key, owner, baseUrl]);\n\n const recordSession = useCallback((update: OnrampHistoryUpdate) => {\n // Archive delayed responses under the initiating wallet without changing the wallet currently shown.\n const paymentOwner = update.ownerAddress.toLowerCase();\n const paymentKey = getOnrampHistoryStorageKey(paymentOwner, baseUrl);\n const isCurrentScope = scopeRef.current.key === paymentKey;\n const current = isCurrentScope && historyRef.current.key === paymentKey\n ? historyRef.current.entries : readOnrampHistory(paymentOwner, baseUrl);\n const entries = upsertOnrampHistory(current, update);\n if (entries === current) return;\n writeOnrampHistory(paymentOwner, baseUrl, entries);\n if (isCurrentScope) {\n const next = { key: paymentKey, entries };\n historyRef.current = next;\n setHistory(next);\n }\n }, [baseUrl]);\n\n const entries = history.key === key ? history.entries : [];\n const pendingIds = entries.filter((entry) => !isOnrampTerminalState(entry.session.state))\n .map((entry) => entry.session.sessionId!).sort().join(\"|\");\n\n useEffect(() => {\n if (!active || !owner || !pendingIds) return;\n const poller = startOnrampPolling({\n fetchSession: async (signal) => {\n if (document.visibilityState === \"hidden\") return;\n const pending = historyRef.current.entries\n .filter((entry) => !isOnrampTerminalState(entry.session.state));\n for (const entry of pending) {\n if (signal.aborted) return;\n try {\n const session = await fetchOnrampSession(baseUrl, entry.session.sessionId!, signal);\n if (signal.aborted) return;\n logOnramp(\"history.poll.status\", { sessionId: session.sessionId, state: session.state });\n recordSession({ ownerAddress: owner, session });\n } catch (error) {\n if (!signal.aborted) logOnramp(\"history.poll.retry\", { sessionId: entry.session.sessionId, error });\n }\n }\n },\n onData: () => historyRef.current.entries.every((entry) => isOnrampTerminalState(entry.session.state)),\n onError: (error) => logOnramp(\"history.poll.retry\", { error }),\n intervalMs: 5000,\n });\n const refresh = () => { if (document.visibilityState !== \"hidden\") void poller.refresh(); };\n window.addEventListener(\"focus\", refresh);\n window.addEventListener(\"online\", refresh);\n document.addEventListener(\"visibilitychange\", refresh);\n return () => {\n poller.stop();\n window.removeEventListener(\"focus\", refresh);\n window.removeEventListener(\"online\", refresh);\n document.removeEventListener(\"visibilitychange\", refresh);\n };\n }, [active, owner, key, baseUrl, pendingIds, recordSession]);\n\n return { entries, recordSession };\n};\n", + "type": "registry:component", + "target": "components/nexus/utils/use-onramp-history.ts" + }, + { + "path": "registry/avail-widgets/nexus-widget/utils/use-onramp-wallet.ts", + "content": "import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { EthereumProvider } from \"@avail-project/nexus-core\";\nimport { isAddress, zeroAddress, type Address, type WalletClient } from \"viem\";\nimport { logOnramp } from \"./onramp-session\";\n\ntype ConnectionProvider = EthereumProvider & {\n connected?: boolean;\n isConnected?: () => boolean;\n session?: { expiry?: number } | null;\n on?: (event: string, listener: (...args: any[]) => void) => unknown;\n removeListener?: (event: string, listener: (...args: any[]) => void) => unknown;\n};\n\nexport type GetOnrampWalletProvider = () => Promise;\n\n/** Bound read-only probes even when a wallet transport never resolves its request. */\nexport function withOnrampWalletTimeout(\n operation: () => Promise,\n signal: AbortSignal,\n timeoutMs = 8000,\n): Promise {\n return new Promise((resolve, reject) => {\n const finish = () => {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", abort);\n };\n const abort = () => {\n finish();\n reject(new Error(\"Wallet check cancelled.\"));\n };\n const timer = setTimeout(() => {\n finish();\n reject(new Error(\"Wallet did not respond. Reconnect your wallet.\"));\n }, timeoutMs);\n signal.addEventListener(\"abort\", abort, { once: true });\n if (signal.aborted) return abort();\n Promise.resolve()\n .then(() => {\n signal.throwIfAborted();\n return operation();\n })\n .then(\n value => { finish(); resolve(value); },\n error => { finish(); reject(error); },\n );\n });\n}\n\nexport async function readOnrampWalletAddress(\n provider: EthereumProvider,\n): Promise
{\n const connection = provider as ConnectionProvider;\n const sessionIsInactive = () =>\n connection.connected === false ||\n connection.isConnected?.() === false ||\n (\"session\" in connection && !connection.session) ||\n (typeof connection.session?.expiry === \"number\" &&\n connection.session.expiry * 1000 <= Date.now());\n if (sessionIsInactive()) return undefined;\n const [accounts, chainId] = await Promise.all([\n provider.request({ method: \"eth_accounts\" }),\n provider.request({ method: \"eth_chainId\" }),\n ]);\n const address = Array.isArray(accounts) ? accounts[0] : undefined;\n return !sessionIsInactive() && Number(chainId) > 0 &&\n typeof address === \"string\" && isAddress(address) && address !== zeroAddress\n ? (address as Address)\n : undefined;\n}\n\n/** Only the active connector is inspected; a persisted address is never proof of connection. */\nexport function useOnrampWallet({\n getProvider,\n walletClient,\n walletConnected,\n}: {\n getProvider: GetOnrampWalletProvider;\n walletClient?: WalletClient | null;\n walletConnected: boolean;\n}) {\n const [verified, setVerified] = useState<{\n address?: Address;\n client?: WalletClient | null;\n getter?: GetOnrampWalletProvider;\n revision: number;\n }>({ revision: 0 });\n const [checking, setChecking] = useState(false);\n const checkRef = useRef<() => Promise
>(async () => undefined);\n const check = useCallback(() => checkRef.current(), []);\n\n useEffect(() => {\n const lifetime = new AbortController();\n let provider: ConnectionProvider | undefined;\n let inFlight: Promise
| undefined;\n let epoch = 0;\n let providerDisconnected = false;\n let backgroundChecksPaused = false;\n const update = (address?: Address) => {\n if (lifetime.signal.aborted) return;\n setVerified(previous => {\n if (previous.address === address && previous.client === walletClient &&\n previous.getter === getProvider) return previous;\n logOnramp(\"wallet.connection\", { address, connected: Boolean(address) });\n return {\n address, client: walletClient, getter: getProvider,\n revision: previous.revision + 1,\n };\n });\n };\n const changed = () => {\n epoch++;\n providerDisconnected = false;\n update();\n void checkConnection();\n };\n const disconnected = () => {\n epoch++;\n providerDisconnected = true;\n update();\n logOnramp(\"wallet.disconnected\");\n };\n // Switching to the deposit chain must not look like an account disconnect.\n const chainChanged = () => { void checkConnection(); };\n const events: Array<[string, (...args: any[]) => void]> = [\n [\"accountsChanged\", changed],\n [\"chainChanged\", chainChanged],\n [\"connect\", changed],\n [\"disconnect\", disconnected],\n [\"session_delete\", disconnected],\n [\"session_expire\", disconnected],\n ];\n const detach = () => events.forEach(([event, handler]) =>\n provider?.removeListener?.(event, handler));\n const checkConnection = (): Promise
=> {\n if (lifetime.signal.aborted) return Promise.resolve(undefined);\n if (inFlight) return inFlight;\n if (!walletConnected || !walletClient) {\n setChecking(false);\n update();\n return Promise.resolve(undefined);\n }\n const runEpoch = epoch;\n setChecking(true);\n inFlight = withOnrampWalletTimeout(async () => {\n const activeProvider = (await getProvider()) as ConnectionProvider | undefined;\n if (lifetime.signal.aborted || runEpoch !== epoch) return undefined;\n if (activeProvider !== provider) {\n detach();\n provider = activeProvider;\n providerDisconnected = false;\n if (typeof provider?.on === \"function\" && typeof provider.removeListener === \"function\") {\n events.forEach(([event, handler]) => provider?.on?.(event, handler));\n }\n }\n if (!activeProvider || providerDisconnected) return undefined;\n const address = await readOnrampWalletAddress(activeProvider);\n backgroundChecksPaused = false;\n // The signing client must belong to this live provider account too.\n return address && walletClient.account?.address.toLowerCase() === address.toLowerCase()\n ? address : undefined;\n }, lifetime.signal).catch(error => {\n // EIP-1193 cannot cancel a stuck transport request. Avoid stacking automatic\n // probes after failure; a user action, focus or provider event can retry.\n backgroundChecksPaused = true;\n if (!lifetime.signal.aborted) logOnramp(\"wallet.check_failed\", { error });\n return undefined;\n }).then(address => {\n if (lifetime.signal.aborted || runEpoch !== epoch) return undefined;\n update(address);\n return address;\n }).finally(() => {\n inFlight = undefined;\n if (!lifetime.signal.aborted) setChecking(false);\n });\n return inFlight;\n };\n checkRef.current = checkConnection;\n const wake = () => { void checkConnection(); };\n const visible = () => { if (document.visibilityState === \"visible\") wake(); };\n wake();\n const timer = setInterval(() => {\n if (!backgroundChecksPaused) wake();\n }, 5000);\n window.addEventListener(\"focus\", wake);\n window.addEventListener(\"online\", wake);\n document.addEventListener(\"visibilitychange\", visible);\n return () => {\n lifetime.abort();\n clearInterval(timer);\n detach();\n window.removeEventListener(\"focus\", wake);\n window.removeEventListener(\"online\", wake);\n document.removeEventListener(\"visibilitychange\", visible);\n };\n }, [getProvider, walletClient, walletConnected]);\n\n const address = walletConnected && verified.getter === getProvider &&\n verified.address?.toLowerCase() === walletClient?.account?.address.toLowerCase()\n ? verified.address : undefined;\n return { address, revision: verified.revision, checking, check };\n}\n", + "type": "registry:component", + "target": "components/nexus/utils/use-onramp-wallet.ts" + }, { "path": "registry/avail-widgets/common/components/ErrorBoundary.tsx", "content": "\"use client\";\n\nimport { Component, type ErrorInfo, type ReactNode } from \"react\";\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error boundary component that catches JavaScript errors in child components.\n * Displays a fallback UI instead of crashing the entire widget.\n *\n * @example\n * Something went wrong}\n * onError={(error) => console.error(error)}\n * >\n * \n * \n */\nexport class ErrorBoundary extends Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n console.error(\"ErrorBoundary caught an error:\", error, errorInfo);\n this.props.onError?.(error, errorInfo);\n }\n\n render(): ReactNode {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n
\n
\n Something went wrong\n
\n

\n An unexpected error occurred. Please try again.\n

\n this.setState({ hasError: false, error: null })}\n className=\"px-4 py-2 text-sm font-medium text-primary-foreground bg-primary rounded-md hover:bg-primary/90 transition-colors\"\n >\n Try again\n \n
\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * A more specific error boundary for widget containers with reset capability.\n */\ninterface WidgetErrorBoundaryProps extends ErrorBoundaryProps {\n widgetName?: string;\n onReset?: () => void;\n}\n\nexport class WidgetErrorBoundary extends Component<\n WidgetErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: WidgetErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n console.error(\n `WidgetErrorBoundary [${this.props.widgetName ?? \"Unknown\"}]:`,\n error,\n errorInfo\n );\n this.props.onError?.(error, errorInfo);\n }\n\n handleReset = (): void => {\n this.props.onReset?.();\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n
\n
\n {this.props.widgetName\n ? `${this.props.widgetName} encountered an error`\n : \"Widget error\"}\n
\n

\n {this.state.error?.message || \"An unexpected error occurred.\"}\n

\n \n Reset widget\n \n
\n );\n }\n\n return this.props.children;\n }\n}\n", @@ -242,7 +284,7 @@ }, { "path": "registry/avail-widgets/common/utils/constant.ts", - "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", + "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n ARC: 5042,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n [SUPPORTED_CHAINS.ARC]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arc/logo.png\",\n name: \"Arc\",\n nativeCurrency: { name: \"USDC\", symbol: \"USDC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.arc.market\"],\n rpcUrls: [\"https://rpc.arc.market\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n [SUPPORTED_CHAINS.ARC]: \"Arc\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 5042: \"0x0000000000000000000000000000000000000000\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", "type": "registry:component", "target": "components/common/utils/constant.ts" }, @@ -254,7 +296,7 @@ }, { "path": "registry/avail-widgets/common/utils/transaction-flow.ts", - "content": "import {\n type NexusNetwork,\n type NexusClient,\n} from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n chainId === SUPPORTED_CHAINS.BNB\n ) {\n return 18;\n }\n return fallback;\n};\n", + "content": "import { type NexusNetwork, type NexusClient } from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n (chainId === SUPPORTED_CHAINS.BNB || chainId === SUPPORTED_CHAINS.ARC)\n ) {\n return 18;\n }\n return fallback;\n};\n", "type": "registry:component", "target": "components/common/utils/transaction-flow.ts" } diff --git a/public/r/swaps.json b/public/r/swaps.json index 6247a4ab..79383c59 100644 --- a/public/r/swaps.json +++ b/public/r/swaps.json @@ -5,7 +5,7 @@ "title": "Swaps", "description": "Deprecated: use Nexus Widget instead. Legacy swap tokens across chains component.", "dependencies": [ - "@avail-project/nexus-core@2.2.3", + "@avail-project/nexus-core@2.5.0", "lucide-react", "viem" ], @@ -210,7 +210,7 @@ }, { "path": "registry/avail-widgets/common/utils/constant.ts", - "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", + "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n ARC: 5042,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n [SUPPORTED_CHAINS.ARC]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arc/logo.png\",\n name: \"Arc\",\n nativeCurrency: { name: \"USDC\", symbol: \"USDC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.arc.market\"],\n rpcUrls: [\"https://rpc.arc.market\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n [SUPPORTED_CHAINS.ARC]: \"Arc\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 5042: \"0x0000000000000000000000000000000000000000\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", "type": "registry:component", "target": "components/common/utils/constant.ts" }, @@ -222,7 +222,7 @@ }, { "path": "registry/avail-widgets/common/utils/transaction-flow.ts", - "content": "import {\n type NexusNetwork,\n type NexusClient,\n} from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n chainId === SUPPORTED_CHAINS.BNB\n ) {\n return 18;\n }\n return fallback;\n};\n", + "content": "import { type NexusNetwork, type NexusClient } from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n (chainId === SUPPORTED_CHAINS.BNB || chainId === SUPPORTED_CHAINS.ARC)\n ) {\n return 18;\n }\n return fallback;\n};\n", "type": "registry:component", "target": "components/common/utils/transaction-flow.ts" } diff --git a/public/r/transfer.json b/public/r/transfer.json index da7e22ac..d6ffa04a 100644 --- a/public/r/transfer.json +++ b/public/r/transfer.json @@ -5,7 +5,7 @@ "title": "Fast Transfer", "description": "Deprecated: use Nexus Widget instead. A legacy component built with Nexus to enable cross chain transfer.", "dependencies": [ - "@avail-project/nexus-core@2.2.3", + "@avail-project/nexus-core@2.5.0", "lucide-react", "viem" ], @@ -183,7 +183,7 @@ }, { "path": "registry/avail-widgets/common/utils/constant.ts", - "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", + "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n ARC: 5042,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n [SUPPORTED_CHAINS.ARC]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arc/logo.png\",\n name: \"Arc\",\n nativeCurrency: { name: \"USDC\", symbol: \"USDC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.arc.market\"],\n rpcUrls: [\"https://rpc.arc.market\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n [SUPPORTED_CHAINS.ARC]: \"Arc\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 5042: \"0x0000000000000000000000000000000000000000\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", "type": "registry:component", "target": "components/common/utils/constant.ts" }, @@ -195,7 +195,7 @@ }, { "path": "registry/avail-widgets/common/utils/transaction-flow.ts", - "content": "import {\n type NexusNetwork,\n type NexusClient,\n} from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n chainId === SUPPORTED_CHAINS.BNB\n ) {\n return 18;\n }\n return fallback;\n};\n", + "content": "import { type NexusNetwork, type NexusClient } from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n (chainId === SUPPORTED_CHAINS.BNB || chainId === SUPPORTED_CHAINS.ARC)\n ) {\n return 18;\n }\n return fallback;\n};\n", "type": "registry:component", "target": "components/common/utils/transaction-flow.ts" } diff --git a/public/r/unified-balance.json b/public/r/unified-balance.json index 39807f3a..37efd214 100644 --- a/public/r/unified-balance.json +++ b/public/r/unified-balance.json @@ -5,7 +5,7 @@ "title": "Unified Balance", "description": "Deprecated: use Nexus Widget instead. Unified Balance has been removed in favor of Nexus Widget's inline balance views.", "dependencies": [ - "@avail-project/nexus-core@2.2.3", + "@avail-project/nexus-core@2.5.0", "lucide-react" ], "registryDependencies": [ diff --git a/public/r/view-history.json b/public/r/view-history.json index 9179fe18..9484dc3e 100644 --- a/public/r/view-history.json +++ b/public/r/view-history.json @@ -5,7 +5,7 @@ "title": "View History", "description": "Deprecated: use Nexus Widget instead. View History has been removed. Use sdk.getMyIntents() for programmatic access.", "dependencies": [ - "@avail-project/nexus-core@2.2.3", + "@avail-project/nexus-core@2.5.0", "lucide-react" ], "registryDependencies": [ @@ -134,7 +134,7 @@ }, { "path": "registry/avail-widgets/common/utils/constant.ts", - "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", + "content": "import { formatUnits, parseUnits } from \"viem\";\n\nexport const SUPPORTED_CHAINS = {\n ETHEREUM: 1,\n BASE: 8453,\n ARBITRUM: 42_161,\n OPTIMISM: 10,\n POLYGON: 137,\n AVALANCHE: 43_114,\n SCROLL: 534_352,\n MEGAETH: 4326,\n KAIA: 8217,\n BNB: 56,\n MONAD: 143,\n HYPEREVM: 999,\n CITREA: 4114,\n ARC: 5042,\n SEPOLIA: 11_155_111,\n BASE_SEPOLIA: 84_532,\n ARBITRUM_SEPOLIA: 421_614,\n OPTIMISM_SEPOLIA: 11_155_420,\n POLYGON_AMOY: 80_002,\n MONAD_TESTNET: 10_143,\n} as const;\n\ninterface ChainMetadata {\n blockExplorerUrls: string[];\n logo: string;\n name: string;\n nativeCurrency: {\n decimals: number;\n name: string;\n symbol: string;\n };\n rpcUrls?: string[];\n}\n\nexport const CHAIN_METADATA: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Ethereum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://optimistic.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://polygonscan.com\"],\n },\n [SUPPORTED_CHAINS.AVALANCHE]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/avalanche/logo.png\",\n name: \"Avalanche\",\n nativeCurrency: { name: \"AVAX\", symbol: \"AVAX\", decimals: 18 },\n blockExplorerUrls: [\"https://snowtrace.io\"],\n },\n [SUPPORTED_CHAINS.SCROLL]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/scroll/logo.png\",\n name: \"Scroll\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://scrollscan.com\"],\n },\n [SUPPORTED_CHAINS.MEGAETH]: {\n logo: \"https://files.availproject.org/fastbridge/megaeth/megaeth-favicon.svg\",\n name: \"MegaETH\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://mega.etherscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/megaeth\"],\n },\n [SUPPORTED_CHAINS.KAIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/kaia/logo.png\",\n name: \"Kaia\",\n nativeCurrency: { name: \"KAIA\", symbol: \"KAIA\", decimals: 18 },\n blockExplorerUrls: [\"https://kaiascan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/kaia\"],\n },\n [SUPPORTED_CHAINS.MONAD]: {\n logo: \"https://files.availproject.org/fastbridge/monad/monad-favicon.svg\",\n name: \"Monad\",\n nativeCurrency: { name: \"Monad\", symbol: \"MON\", decimals: 18 },\n blockExplorerUrls: [\"https://monadscan.com\"],\n rpcUrls: [\"https://rpcs.avail.so/monad\"],\n },\n [SUPPORTED_CHAINS.HYPEREVM]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/hyperevm/logo.png\",\n name: \"HyperEVM\",\n nativeCurrency: { name: \"Hype\", symbol: \"HYPE\", decimals: 18 },\n blockExplorerUrls: [\"https://hyperevmscan.io\"],\n rpcUrls: [\"https://rpcs.avail.so/hyperevm\"],\n },\n [SUPPORTED_CHAINS.BNB]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/bnb/logo.png\",\n name: \"BNB Smart Chain\",\n nativeCurrency: { name: \"BNB\", symbol: \"BNB\", decimals: 18 },\n blockExplorerUrls: [\"https://bscscan.com\"],\n },\n [SUPPORTED_CHAINS.CITREA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/citrea/logo.png\",\n name: \"Citrea\",\n nativeCurrency: { name: \"cBTC\", symbol: \"cBTC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.citrea.xyz\"],\n },\n [SUPPORTED_CHAINS.ARC]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arc/logo.png\",\n name: \"Arc\",\n nativeCurrency: { name: \"USDC\", symbol: \"USDC\", decimals: 18 },\n blockExplorerUrls: [\"https://explorer.arc.market\"],\n rpcUrls: [\"https://rpc.arc.market\"],\n },\n // Testnets\n [SUPPORTED_CHAINS.SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png\",\n name: \"Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/base/logo.png\",\n name: \"Base Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.basescan.org\"],\n },\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arbitrum/logo.png\",\n name: \"Arbitrum Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia.arbiscan.io\"],\n },\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/optimism/logo.png\",\n name: \"Optimism Sepolia\",\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n blockExplorerUrls: [\"https://sepolia-optimism.etherscan.io\"],\n },\n [SUPPORTED_CHAINS.POLYGON_AMOY]: {\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/polygon/logo.png\",\n name: \"Polygon Amoy\",\n nativeCurrency: { name: \"POL\", symbol: \"POL\", decimals: 18 },\n blockExplorerUrls: [\"https://amoy.polygonscan.com\"],\n },\n};\n\nexport const TOKEN_METADATA = {\n ETH: {\n decimals: 18,\n name: \"Ethereum\",\n symbol: \"ETH\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/eth/logo.png\",\n },\n USDC: {\n decimals: 6,\n name: \"USD Coin\",\n symbol: \"USDC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdc/logo.png\",\n },\n USDT: {\n decimals: 6,\n name: \"Tether USD\",\n symbol: \"USDT\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/usdt/logo.png\",\n },\n DAI: {\n decimals: 18,\n name: \"Dai Stablecoin\",\n symbol: \"DAI\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/dai/logo.png\",\n },\n WBTC: {\n decimals: 8,\n name: \"Wrapped BTC\",\n symbol: \"WBTC\",\n logo: \"https://raw.githubusercontent.com/availproject/nexus-assets/main/tokens/wbtc/logo.png\",\n },\n} as const;\n\nexport const SHORT_CHAIN_NAME: Record = {\n [SUPPORTED_CHAINS.ETHEREUM]: \"Ethereum\",\n [SUPPORTED_CHAINS.BASE]: \"Base\",\n [SUPPORTED_CHAINS.ARBITRUM]: \"Arbitrum\",\n [SUPPORTED_CHAINS.OPTIMISM]: \"Optimism\",\n [SUPPORTED_CHAINS.POLYGON]: \"Polygon\",\n [SUPPORTED_CHAINS.AVALANCHE]: \"Avalanche\",\n [SUPPORTED_CHAINS.SCROLL]: \"Scroll\",\n [SUPPORTED_CHAINS.MEGAETH]: \"MegaETH\",\n [SUPPORTED_CHAINS.KAIA]: \"Kaia\",\n [SUPPORTED_CHAINS.BNB]: \"BNB\",\n [SUPPORTED_CHAINS.MONAD]: \"Monad\",\n [SUPPORTED_CHAINS.HYPEREVM]: \"HyperEVM\",\n [SUPPORTED_CHAINS.CITREA]: \"Citrea\",\n [SUPPORTED_CHAINS.ARC]: \"Arc\",\n // [SUPPORTED_CHAINS.TRON]: \"Tron\",\n [SUPPORTED_CHAINS.SEPOLIA]: \"Sepolia\",\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: \"Base Sepolia\",\n [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: \"Arbitrum Sepolia\",\n [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: \"Optimism Sepolia\",\n [SUPPORTED_CHAINS.POLYGON_AMOY]: \"Polygon Amoy\",\n [SUPPORTED_CHAINS.MONAD_TESTNET]: \"Monad Testnet\",\n // [SUPPORTED_CHAINS.TRON_SHASTA]: \"Tron Shasta\",\n} as const;\n\nexport type SdkChainWithSwapSupport = {\n chain?: { id?: number | null } | null;\n id?: number | null;\n swapSupported?: boolean | null;\n};\n\nexport type SdkChainListWithSwapSupport =\n | readonly SdkChainWithSwapSupport[]\n | null\n | undefined;\n\nconst getSdkChainId = (chain: SdkChainWithSwapSupport) => {\n const rawId = chain.id ?? chain.chain?.id;\n if (rawId == null) {\n return undefined;\n }\n\n const chainId = Number(rawId);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport function getSdkSwapSupportedChainIds(\n chains: SdkChainListWithSwapSupport\n): Set | null {\n if (!chains?.length) {\n return null;\n }\n\n const hasExplicitSwapSupport = chains.some(\n (chain) => typeof chain.swapSupported === \"boolean\"\n );\n if (!hasExplicitSwapSupport) {\n return null;\n }\n\n const supportedIds = new Set();\n for (const chain of chains) {\n if (chain.swapSupported !== true) {\n continue;\n }\n\n const chainId = getSdkChainId(chain);\n if (chainId) {\n supportedIds.add(chainId);\n }\n }\n\n return supportedIds;\n}\n\nexport function isSwapSupportedBySdkChainList(\n chainId: number | null | undefined,\n chains: SdkChainListWithSwapSupport\n): boolean {\n if (!chainId) {\n return false;\n }\n\n const sdkSupportedIds = getSdkSwapSupportedChainIds(chains);\n if (sdkSupportedIds) {\n return sdkSupportedIds.has(Number(chainId));\n }\n\n return true;\n}\n\nexport function getShortChainName(\n chainId?: number,\n fallbackName?: string\n): string {\n if (!chainId) {\n return fallbackName ?? \"\";\n }\n return SHORT_CHAIN_NAME[chainId] ?? fallbackName ?? String(chainId);\n}\n\nexport const TOKEN_IMAGES: Record = {\n BNB: \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n KAIA: \"https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png\",\n SOPH: \"https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png\",\n USDC: \"https://coin-images.coingecko.com/coins/images/6319/large/usdc.png\",\n USDM: \"https://raw.githubusercontent.com/availproject/nexus-assets/refs/heads/main/tokens/usdm/logo.png\",\n USDS: \"https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683\",\n USDT: \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n \"USD₮0\":\n \"https://coin-images.coingecko.com/coins/images/35023/large/USDT.png\",\n WETH: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880\",\n};\n\nconst DEFAULT_SAFETY_MARGIN = 0.01; // 1%\nconst TRAILING_DECIMAL_ZERO_REGEX = /(\\.\\d*?[1-9])0+$/u;\nconst ZERO_DECIMAL_REGEX = /\\.0+$/u;\nconst LONE_DECIMAL_POINT_REGEX = /^\\.$/u;\n\n/**\n * Compute an amount string for fraction buttons (25%, 50%, 75%, 100%).\n *\n * @param balanceStr - user's balance as a human decimal string (e.g. \"12.345\") OR as base-unit integer string if `balanceIsBaseUnits` true\n * @param fraction - fraction e.g. 0.25, 0.5, 0.75, 1\n * @param decimals - token decimals (6 for USDC/USDT, 18 for ETH)\n * @param safetyMargin - 0.01 for 1% default\n * @param balanceIsBaseUnits - if true, balanceStr is already base units integer string (wei / smallest unit)\n * @returns decimal string clipped to token decimals (rounded down)\n */\nexport function computeAmountFromFraction(\n balanceStr: string,\n fraction: number,\n decimals: number,\n safetyMargin = DEFAULT_SAFETY_MARGIN,\n balanceIsBaseUnits = false\n): string {\n if (!balanceStr) {\n return \"0\";\n }\n\n // parse balance into base units (BigInt)\n const balanceUnits: bigint = balanceIsBaseUnits\n ? BigInt(balanceStr)\n : parseUnits(balanceStr, decimals);\n\n if (balanceUnits === BigInt(0)) {\n return \"0\";\n }\n\n // Use an integer precision multiplier to avoid FP issues\n const PREC = 1_000_000; // 1e6 precision for fraction & safety margin\n const safetyMul = BigInt(Math.max(0, Math.floor((1 - safetyMargin) * PREC))); // (1 - safetyMargin) * PREC\n const fractionMul = BigInt(Math.max(0, Math.floor(fraction * PREC))); // fraction * PREC\n\n // Apply safety margin: floor(balance * (1 - safetyMargin))\n const maxAfterSafety = (balanceUnits * safetyMul) / BigInt(PREC);\n\n // Apply fraction and floor: floor(maxAfterSafety * fraction)\n let desiredUnits = (maxAfterSafety * fractionMul) / BigInt(PREC);\n\n // Extra clamp just in case\n if (desiredUnits > balanceUnits) {\n desiredUnits = balanceUnits;\n }\n if (desiredUnits < BigInt(0)) {\n desiredUnits = BigInt(0);\n }\n\n // format back to human readable decimal string with token decimals (formatUnits truncates/keeps decimals)\n // formatUnits will produce exactly decimals digits if fractional part exists; we'll strip trailing zeros.\n const raw = formatUnits(desiredUnits, decimals);\n // strip trailing zeros and possible trailing dot\n return raw\n .replace(TRAILING_DECIMAL_ZERO_REGEX, \"$1\")\n .replace(ZERO_DECIMAL_REGEX, \"\")\n .replace(LONE_DECIMAL_POINT_REGEX, \"0\");\n}\n\nexport const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n});\n\nconst usdFormatterPrecise = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n minimumFractionDigits: 3,\n maximumFractionDigits: 3,\n});\n\n/**\n * Formats USD values for UI.\n * Values between 0 and 0.001 are shown as \"< $0.001\".\n * Values between 0.001 and 0.01 are shown with 3 decimals.\n */\nexport function formatUsdForDisplay(value: number): string {\n if (!Number.isFinite(value)) {\n return usdFormatter.format(0);\n }\n const absValue = Math.abs(value);\n\n if (absValue === 0) {\n return usdFormatter.format(0);\n }\n if (absValue < 0.001) {\n return \"< $0.001\";\n }\n if (absValue < 0.01) {\n return usdFormatterPrecise.format(value);\n }\n\n return usdFormatter.format(value);\n}\n\nexport const TOKEN_CONTRACT_ADDRESSES = {\n USDC: {\n 1: \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n 8453: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n 137: \"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359\",\n 42161: \"0xaf88d065e77c8cc2239327c5edb3a432268e5831\",\n 10: \"0x0b2c639c533813f4aa9d7837caf62653d097ff85\",\n 534352: \"0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4\",\n 43114: \"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e\",\n 56: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n 999: \"0xb88339CB7199b77E23DB6E890353E22632Ba630f\",\n 143: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n 4114: \"0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839\",\n 5042: \"0x0000000000000000000000000000000000000000\",\n 11155111: \"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238\",\n 84532: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n 421614: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n 11155420: \"0x5fd84259d66Cd46123540766Be93DFE6D43130D7\",\n 80002: \"0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582\",\n 10143: \"0xf817257fed379853cDe0fa4F97AB987181B1E5Ea\",\n 5115: \"0xb669dC8cC6D044307Ba45366C0c836eC3c7e31AA\",\n },\n USDT: {\n 1: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n 137: \"0xc2132d05d31c914a87c6611c10748aeb04b58e8f\",\n 42161: \"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\n 8217: \"0xd077a400968890eacc75cdc901f0356c943e4fdb\",\n 10: \"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\n 534352: \"0xf55bec9cafdbe8730f096aa55dad6d22d44099df\",\n 43114: \"0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7\",\n 56: \"0x55d398326f99059fF775485246999027B3197955\",\n 999: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 4114: \"0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4\",\n 4326: \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\",\n 421614: \"0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1\",\n 11155420: \"0x6462693c2F21AC0E517f12641D404895030F7426\",\n 10143: \"0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b\",\n },\n USDM: {\n 4326: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n },\n} as Record>;\n", "type": "registry:component", "target": "components/common/utils/constant.ts" }, @@ -146,7 +146,7 @@ }, { "path": "registry/avail-widgets/common/utils/transaction-flow.ts", - "content": "import {\n type NexusNetwork,\n type NexusClient,\n} from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n chainId === SUPPORTED_CHAINS.BNB\n ) {\n return 18;\n }\n return fallback;\n};\n", + "content": "import { type NexusNetwork, type NexusClient } from \"@avail-project/nexus-core\";\nimport { formatUnits } from \"@avail-project/nexus-core/utils\";\nimport { SUPPORTED_CHAINS } from \"./constant\";\nimport { type Address } from \"viem\";\n\nconst MAX_AMOUNT_REGEX = /^\\d*\\.?\\d+$/;\n\nexport const MAX_AMOUNT_DEBOUNCE_MS = 300;\n\nexport const normalizeMaxAmount = (\n maxAmount?: string | number,\n): string | undefined => {\n if (maxAmount === undefined || maxAmount === null) return undefined;\n const value = String(maxAmount).trim();\n if (!value || value === \".\" || !MAX_AMOUNT_REGEX.test(value)) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return value;\n};\n\nexport const clampAmountToMax = ({\n amount,\n maxAmount,\n nexusSDK,\n token,\n chainId,\n}: {\n amount: string;\n maxAmount?: string;\n nexusSDK: NexusClient;\n token: string;\n chainId: number;\n}): string => {\n if (!maxAmount) return amount;\n try {\n const amountRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n amount,\n token,\n chainId,\n );\n const maxRaw = nexusSDK.convertTokenReadableAmountToBigInt(\n maxAmount,\n token,\n chainId,\n );\n return amountRaw > maxRaw ? maxAmount : amount;\n } catch {\n return amount;\n }\n};\n\nexport const formatAmountForDisplay = (\n amount: bigint,\n decimals: number | undefined,\n nexusSDK: NexusClient,\n): string => {\n if (typeof decimals !== \"number\") return amount.toString();\n const formatted = formatUnits(amount, decimals);\n if (!formatted.includes(\".\")) return formatted;\n const [whole, fraction] = formatted.split(\".\");\n const trimmedFraction = fraction.slice(0, 6).replace(/0+$/, \"\");\n if (!trimmedFraction && whole === \"0\" && amount > BigInt(0)) {\n return \"0.000001\";\n }\n return trimmedFraction ? `${whole}.${trimmedFraction}` : whole;\n};\n\nexport const buildInitialInputs = ({\n type,\n network,\n connectedAddress,\n prefill,\n}: {\n type: \"bridge\" | \"transfer\";\n network: NexusNetwork;\n connectedAddress?: Address;\n prefill?: {\n token: string;\n chainId: number;\n amount?: string;\n recipient?: Address;\n };\n}) => {\n return {\n chain:\n prefill?.chainId ??\n (network === \"testnet\"\n ? SUPPORTED_CHAINS.SEPOLIA\n : SUPPORTED_CHAINS.ETHEREUM),\n token: prefill?.token ?? \"USDC\",\n amount: prefill?.amount ?? undefined,\n recipient:\n (prefill?.recipient as `0x${string}`) ??\n (type === \"bridge\" ? connectedAddress : undefined),\n };\n};\n\nexport const getCoverageDecimals = ({\n type,\n token,\n chainId,\n fallback,\n}: {\n type: \"bridge\" | \"transfer\";\n token?: string;\n chainId?: number;\n fallback: number | undefined;\n}) => {\n if (token === \"USDM\") return 18;\n if (\n type === \"bridge\" &&\n token === \"USDC\" &&\n (chainId === SUPPORTED_CHAINS.BNB || chainId === SUPPORTED_CHAINS.ARC)\n ) {\n return 18;\n }\n return fallback;\n};\n", "type": "registry:component", "target": "components/common/utils/transaction-flow.ts" } diff --git a/registry.config.json b/registry.config.json index 08a3ff56..cdea01c9 100644 --- a/registry.config.json +++ b/registry.config.json @@ -7,7 +7,7 @@ "outputPath": "registry.json", "peerDependencies": ["react", "react-dom"], "pinnedDependencies": { - "@avail-project/nexus-core": "2.4.1" + "@avail-project/nexus-core": "2.5.0" }, "aliases": { "@/lib/utils": "lib/utils.ts", diff --git a/registry.json b/registry.json index ce334245..2eb17009 100644 --- a/registry.json +++ b/registry.json @@ -248,7 +248,7 @@ } ], "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "lucide-react", "viem" ], @@ -609,7 +609,7 @@ } ], "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "clsx", "lucide-react", "tailwind-merge", @@ -807,7 +807,7 @@ } ], "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "lucide-react", "viem" ], @@ -883,16 +883,31 @@ "target": "components/nexus/components/amount-input-unified.tsx", "type": "registry:component" }, + { + "path": "registry/avail-widgets/nexus-widget/components/deposit-funding-method.tsx", + "target": "components/nexus/components/deposit-funding-method.tsx", + "type": "registry:component" + }, { "path": "registry/avail-widgets/nexus-widget/components/deposit-idle-form.tsx", "target": "components/nexus/components/deposit-idle-form.tsx", "type": "registry:component" }, + { + "path": "registry/avail-widgets/nexus-widget/components/deposit-onramp-flow.tsx", + "target": "components/nexus/components/deposit-onramp-flow.tsx", + "type": "registry:component" + }, { "path": "registry/avail-widgets/nexus-widget/components/nexus-widget-progress-screen.tsx", "target": "components/nexus/components/nexus-widget-progress-screen.tsx", "type": "registry:component" }, + { + "path": "registry/avail-widgets/nexus-widget/components/onramp-history-card.tsx", + "target": "components/nexus/components/onramp-history-card.tsx", + "type": "registry:component" + }, { "path": "registry/avail-widgets/nexus-widget/components/pay-using-selector.tsx", "target": "components/nexus/components/pay-using-selector.tsx", @@ -978,6 +993,26 @@ "target": "components/nexus/utils/deposit-source-selection.ts", "type": "registry:component" }, + { + "path": "registry/avail-widgets/nexus-widget/utils/onramp-history.ts", + "target": "components/nexus/utils/onramp-history.ts", + "type": "registry:component" + }, + { + "path": "registry/avail-widgets/nexus-widget/utils/onramp-session.ts", + "target": "components/nexus/utils/onramp-session.ts", + "type": "registry:component" + }, + { + "path": "registry/avail-widgets/nexus-widget/utils/use-onramp-history.ts", + "target": "components/nexus/utils/use-onramp-history.ts", + "type": "registry:component" + }, + { + "path": "registry/avail-widgets/nexus-widget/utils/use-onramp-wallet.ts", + "target": "components/nexus/utils/use-onramp-wallet.ts", + "type": "registry:component" + }, { "path": "registry/avail-widgets/common/components/ErrorBoundary.tsx", "target": "components/common/components/ErrorBoundary.tsx", @@ -1075,7 +1110,7 @@ } ], "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "decimal.js", "lucide-react", "viem", @@ -1105,7 +1140,7 @@ } ], "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "wagmi" ] }, @@ -1358,7 +1393,7 @@ } ], "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "lucide-react", "viem" ], @@ -1571,7 +1606,7 @@ } ], "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "lucide-react", "viem" ], @@ -1609,7 +1644,7 @@ } ], "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "lucide-react" ], "registryDependencies": [ @@ -1762,7 +1797,7 @@ } ], "dependencies": [ - "@avail-project/nexus-core@2.4.1", + "@avail-project/nexus-core@2.5.0", "lucide-react" ], "registryDependencies": [ diff --git a/registry/avail-widgets/common/utils/constant.ts b/registry/avail-widgets/common/utils/constant.ts index a7ed6ddd..d01ff4be 100644 --- a/registry/avail-widgets/common/utils/constant.ts +++ b/registry/avail-widgets/common/utils/constant.ts @@ -14,6 +14,7 @@ export const SUPPORTED_CHAINS = { MONAD: 143, HYPEREVM: 999, CITREA: 4114, + ARC: 5042, SEPOLIA: 11_155_111, BASE_SEPOLIA: 84_532, ARBITRUM_SEPOLIA: 421_614, @@ -117,6 +118,13 @@ export const CHAIN_METADATA: Record = { nativeCurrency: { name: "cBTC", symbol: "cBTC", decimals: 18 }, blockExplorerUrls: ["https://explorer.citrea.xyz"], }, + [SUPPORTED_CHAINS.ARC]: { + logo: "https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/arc/logo.png", + name: "Arc", + nativeCurrency: { name: "USDC", symbol: "USDC", decimals: 18 }, + blockExplorerUrls: ["https://explorer.arc.market"], + rpcUrls: ["https://rpc.arc.market"], + }, // Testnets [SUPPORTED_CHAINS.SEPOLIA]: { logo: "https://raw.githubusercontent.com/availproject/nexus-assets/main/chains/ethereum/logo.png", @@ -197,6 +205,7 @@ export const SHORT_CHAIN_NAME: Record = { [SUPPORTED_CHAINS.MONAD]: "Monad", [SUPPORTED_CHAINS.HYPEREVM]: "HyperEVM", [SUPPORTED_CHAINS.CITREA]: "Citrea", + [SUPPORTED_CHAINS.ARC]: "Arc", // [SUPPORTED_CHAINS.TRON]: "Tron", [SUPPORTED_CHAINS.SEPOLIA]: "Sepolia", [SUPPORTED_CHAINS.BASE_SEPOLIA]: "Base Sepolia", @@ -411,6 +420,7 @@ export const TOKEN_CONTRACT_ADDRESSES = { 999: "0xb88339CB7199b77E23DB6E890353E22632Ba630f", 143: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603", 4114: "0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839", + 5042: "0x0000000000000000000000000000000000000000", 11155111: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", 84532: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", 421614: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d", diff --git a/registry/avail-widgets/common/utils/transaction-flow.ts b/registry/avail-widgets/common/utils/transaction-flow.ts index 189879e7..bfc76ccb 100644 --- a/registry/avail-widgets/common/utils/transaction-flow.ts +++ b/registry/avail-widgets/common/utils/transaction-flow.ts @@ -1,7 +1,4 @@ -import { - type NexusNetwork, - type NexusClient, -} from "@avail-project/nexus-core"; +import { type NexusNetwork, type NexusClient } from "@avail-project/nexus-core"; import { formatUnits } from "@avail-project/nexus-core/utils"; import { SUPPORTED_CHAINS } from "./constant"; import { type Address } from "viem"; @@ -115,7 +112,7 @@ export const getCoverageDecimals = ({ if ( type === "bridge" && token === "USDC" && - chainId === SUPPORTED_CHAINS.BNB + (chainId === SUPPORTED_CHAINS.BNB || chainId === SUPPORTED_CHAINS.ARC) ) { return 18; } diff --git a/registry/avail-widgets/nexus-widget/components/deposit-funding-method.tsx b/registry/avail-widgets/nexus-widget/components/deposit-funding-method.tsx new file mode 100644 index 00000000..a5ab8b5f --- /dev/null +++ b/registry/avail-widgets/nexus-widget/components/deposit-funding-method.tsx @@ -0,0 +1,475 @@ +// biome-ignore-all lint: NexusWidget registry component from shadcn registry. + +import React from "react"; +import { nexusWidgetTheme } from "../theme"; + +type FundingMethod = "wallet" | "local-currency"; + +interface DepositFundingMethodProps { + enableOnRamp?: boolean; + isBalanceLoading?: boolean; + onSelectLocalCurrency: () => void; + onSelectWallet: () => void; + primaryButtonForeground: string; + totalBalance: string; +} + +interface LogoItem { + alt: string; + height?: string; + invertDark?: boolean; + url: string; + width?: string; +} + +const WALLET_LOGOS: LogoItem[] = [ + { + alt: "MetaMask", + height: "22px", + url: "https://files.availproject.org/widgets/assets/metamask.png", + width: "22px", + }, + { + alt: "Rabby", + height: "22px", + url: "https://files.availproject.org/widgets/assets/rabby.png", + width: "22px", + }, + { + alt: "Zerion", + height: "20px", + url: "https://files.availproject.org/widgets/assets/zerion.png", + width: "20px", + }, +]; + +const CASH_LOGOS: LogoItem[] = [ + { + alt: "Mastercard", + height: "15px", + url: "https://files.availproject.org/widgets/assets/mastercard.png", + width: "24px", + }, + { + alt: "Apple Pay", + height: "20px", + invertDark: true, + url: "https://files.availproject.org/widgets/assets/apple-pay.png", + width: "20px", + }, + { + alt: "Google Pay", + height: "20px", + url: "https://files.availproject.org/widgets/assets/google-pay.png", + width: "20px", + }, +]; + +const theme = nexusWidgetTheme; +const brand = "var(--foreground-brand)"; + +const useIsDarkMode = () => { + const [isDark, setIsDark] = React.useState(false); + + React.useEffect(() => { + if (typeof window === "undefined" || typeof document === "undefined") + return; + + const checkDark = () => { + const root = + typeof document !== "undefined" ? document.documentElement : undefined; + const body = typeof document !== "undefined" ? document.body : undefined; + const isDarkClass = Boolean( + root?.classList?.contains("dark") || body?.classList?.contains("dark"), + ); + const isDataThemeDark = root?.getAttribute?.("data-theme") === "dark"; + const prefersDark = + typeof window.matchMedia === "function" + ? Boolean(window.matchMedia("(prefers-color-scheme: dark)")?.matches) + : false; + return Boolean(isDarkClass || isDataThemeDark || prefersDark); + }; + + setIsDark(checkDark()); + + const mediaQuery = + typeof window.matchMedia === "function" + ? window.matchMedia("(prefers-color-scheme: dark)") + : undefined; + const handleMediaChange = () => setIsDark(checkDark()); + mediaQuery?.addEventListener?.("change", handleMediaChange); + + const root = + typeof document !== "undefined" ? document.documentElement : undefined; + let observer: MutationObserver | undefined; + if (root && typeof MutationObserver !== "undefined") { + observer = new MutationObserver(() => { + setIsDark(checkDark()); + }); + observer.observe(root, { + attributes: true, + attributeFilter: ["class", "data-theme"], + }); + } + + return () => { + mediaQuery?.removeEventListener?.("change", handleMediaChange); + observer?.disconnect(); + }; + }, []); + + return isDark; +}; + +function RadioMark({ selected }: { selected: boolean }) { + return ( +