From 3d519049db6fc548be057ba87549864da1250774 Mon Sep 17 00:00:00 2001 From: Charlie Sibbach Date: Tue, 28 Jul 2026 19:18:37 -0700 Subject: [PATCH] Add Circle onramp integration and related updates - Introduced Circle onramp functionality, allowing users to buy crypto directly from the wallet interface. - Added new CircleProvider and related context for managing onramp sessions. - Implemented onramp RPC method for seamless integration with the wallet. - Updated AssetDetails and WalletActions components to include onramp options. - Enhanced documentation to reflect new onramp capabilities and usage instructions. - Added necessary environment configurations for Circle's AppKit integration. --- .../skills/oneshot-embedded-wallet/SKILL.md | 27 +- .github/workflows/Deploy Dev.yaml | 3 + .github/workflows/Deploy Prod.yaml | 3 + .gitignore | 1 + .npmrc | 2 + AGENTS.md | 4 +- Dockerfile | 8 +- README.md | 25 + host/src/components/WalletActions.tsx | 20 + host/src/hooks/useHostTestActions.ts | 23 + package-lock.json | 1853 ++++++++++++++++- package.json | 3 +- skills/oneshot-embedded-wallet/SKILL.md | 25 +- src/circle/CircleContext.tsx | 30 + src/circle/circleChains.ts | 39 + src/circle/circlePopup.ts | 17 + src/circle/onrampTypes.ts | 9 + src/circle/openOnramp.ts | 13 + src/components/AssetDetails.tsx | 28 +- src/components/ModalHost.tsx | 11 + src/components/OnrampView.tsx | 277 +++ .../modals/PurchaseComingSoonModal.tsx | 29 - .../implementations/utils/CircleProvider.ts | 42 + .../implementations/utils/ConfigProvider.ts | 3 + src/lib/implementations/utils/index.ts | 1 + src/lib/interfaces/utils/ICircleProvider.ts | 13 + src/lib/interfaces/utils/index.ts | 2 + src/lib/types/domain/WalletConfig.ts | 4 + src/wallet/WalletProvider.tsx | 8 +- src/wallet/modalTypes.ts | 8 + src/wallet/registerOnramp.ts | 66 + src/wallet/useWalletBoot.ts | 11 + 32 files changed, 2520 insertions(+), 88 deletions(-) create mode 100644 .npmrc create mode 100644 src/circle/CircleContext.tsx create mode 100644 src/circle/circleChains.ts create mode 100644 src/circle/circlePopup.ts create mode 100644 src/circle/onrampTypes.ts create mode 100644 src/circle/openOnramp.ts create mode 100644 src/components/OnrampView.tsx delete mode 100644 src/components/modals/PurchaseComingSoonModal.tsx create mode 100644 src/lib/implementations/utils/CircleProvider.ts create mode 100644 src/lib/interfaces/utils/ICircleProvider.ts create mode 100644 src/wallet/registerOnramp.ts diff --git a/.agents/skills/oneshot-embedded-wallet/SKILL.md b/.agents/skills/oneshot-embedded-wallet/SKILL.md index 4b0ec4f..9c8d8ea 100644 --- a/.agents/skills/oneshot-embedded-wallet/SKILL.md +++ b/.agents/skills/oneshot-embedded-wallet/SKILL.md @@ -3,7 +3,7 @@ name: oneshot-embedded-wallet description: >- Integrate the 1Shot embedded wallet (OWS Host Layer) with @1shotapi/ows-provider. Use when embedding wallet.1shotapi.com, wiring OWSProxy, EIP-1193, credentials, - or custom RPC such as setStyle / focusWallet / addAsset / createAccount for + or custom RPC such as setStyle / focusWallet / addAsset / createAccount / onramp for theming, host-driven focus mode, tracked assets, and first-party Safari create. license: MIT metadata: @@ -232,7 +232,7 @@ Users can also add assets from the Balances tab without a host RPC. The Balances ## Custom RPC — `createAccount` -Used by the first-party **`/create/`** host page (Safari passkey create). Hosts embedding the wallet normally do **not** call this — the branding layer opens `/create/` itself when needed. +Used by the first-party **`/create/`** host page (Safari passkey create). Hosts embedding the wallet normally do **not** call this — the branding layer opens `/create/` itself when needed. Not exposed as a playground button. ```typescript const result = await proxy.rpc("createAccount"); @@ -246,14 +246,32 @@ await proxy.rpc("createAccount", { accountName: "My Wallet" }); |--------|--------|--------| | `createAccount` | `{ accountName?: string }` optional | Runs setup create (passkey + relayer register); returns credential id | +## Custom RPC — `onramp` + +Opens Circle fiat onramp fullscreen inside the Branding Layer for the unlocked EVM address. + +```typescript +await proxy.rpc("onramp", { + chainId: 8453, // optional — decimal chain id for catalog scoping + amount: "50", // optional — amount hint when supported by the kit +}); +// or: await proxy.rpc("onramp", {}); +``` + +| Method | Params | Behavior | +|--------|--------|----------| +| `onramp` | `{ chainId?: number, amount?: string }` | Shows wallet, mounts Circle AppKit onramp; session minted via Relayer `POST /wallet/onramp` | + +Returns `{ ok: true }` when the user closes the onramp view. The Relayer holds the Circle kit key; the browser only receives a single-use session. Inline iframe requires Circle CSP allowlisting of the wallet origin; for local/ngrok testing the branding layer honors `localStorage.setItem("circlePopup", "true")` and uses AppKit `openWindow` instead. + ## Other Host APIs | API | Use | |-----|-----| | `proxy.ethereum.request(...)` | EIP-1193 (accounts, sign, chain, …) | | `proxy.credentials.*` | OID4 offer / present (when enabled in wallet) | -| `proxy.showWallet()` / `hideWallet()` | Host-driven panel (flyout or full-screen drawer on small viewports) without an EIP-1193 call | -| `proxy.rpc(method, params)` | Custom Branding RPC (`setStyle`, `focusWallet`, `unfocusWallet`, `addAsset`, `createAccount`, …) | +| `proxy.showWallet()` / `hideWallet()` | Host-driven flyout without an EIP-1193 call | +| `proxy.rpc(method, params)` | Custom Branding RPC (`setStyle`, `focusWallet`, `unfocusWallet`, `addAsset`, `createAccount`, `onramp`, …) | ## Hard rules @@ -262,3 +280,4 @@ await proxy.rpc("createAccount", { accountName: "My Wallet" }); - Theme with `setStyle`; do not ask integrators to fork CSS for basic brand colors / product name. - Use `focusWallet` / `unfocusWallet` for host-driven single-asset flows; do not expose mode switching in the wallet UI. - Use `addAsset` when the host wants a lasting Balances entry; expect a confirm modal (contrast with `focusWallet`). +- Use `onramp` (or the in-wallet Buy button) for fiat → crypto; do not put the Circle kit key in the Host or Branding Layer. diff --git a/.github/workflows/Deploy Dev.yaml b/.github/workflows/Deploy Dev.yaml index 51525b1..3dc2cbf 100644 --- a/.github/workflows/Deploy Dev.yaml +++ b/.github/workflows/Deploy Dev.yaml @@ -55,8 +55,11 @@ jobs: gcloud --quiet auth configure-docker $GAR_LOCATION-docker.pkg.dev - name: Build Wallet + env: + CLOUDSMITH_TOKEN: ${{ secrets.CLOUDSMITH_TOKEN }} run: |- docker build \ + --secret id=cloudsmith_token,env=CLOUDSMITH_TOKEN \ --tag "$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$PRODUCT_NAME/oneshot-wallet:$GITHUB_SHA" \ --tag "$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$PRODUCT_NAME/oneshot-wallet:${GITHUB_REF##*/}" \ --tag "$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$PRODUCT_NAME/oneshot-wallet:latest" \ diff --git a/.github/workflows/Deploy Prod.yaml b/.github/workflows/Deploy Prod.yaml index 0ba27c3..0811ddd 100644 --- a/.github/workflows/Deploy Prod.yaml +++ b/.github/workflows/Deploy Prod.yaml @@ -53,8 +53,11 @@ jobs: gcloud --quiet auth configure-docker $GAR_LOCATION-docker.pkg.dev - name: Build Wallet + env: + CLOUDSMITH_TOKEN: ${{ secrets.CLOUDSMITH_TOKEN }} run: |- docker build \ + --secret id=cloudsmith_token,env=CLOUDSMITH_TOKEN \ --tag "$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$PRODUCT_NAME/oneshot-wallet:$GITHUB_SHA" \ --tag "$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$PRODUCT_NAME/oneshot-wallet:${GITHUB_REF##*/}" \ --tag "$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$PRODUCT_NAME/oneshot-wallet:latest" \ diff --git a/.gitignore b/.gitignore index a8299ab..48bf058 100644 --- a/.gitignore +++ b/.gitignore @@ -150,3 +150,4 @@ oneshot-wallet-*-deploy oneshot-wallet-*-deploy.pub *-deploy *-deploy.pub +Circle Onramp Kit Beta testing.md diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..e87ec79 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +@crcl-main:registry=https://npm.cloudsmith.io/circle/common-private/ +//npm.cloudsmith.io/circle/common-private/:_authToken=${CLOUDSMITH_TOKEN} diff --git a/AGENTS.md b/AGENTS.md index dae7592..218e7b1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,11 +18,13 @@ Prefer **clean code over backwards compatibility**. Do not add legacy redirects, | `src/lib/types/domain/` | Domain DTOs (e.g. `KnownAsset`, `TrackedAsset`, `WalletConfig`) | | `src/lib/types/events/` | Domain event classes (one file each) | | `src/lib/interfaces/{business,data,utils}/` | Layer interfaces | -| `src/lib/implementations/{business,data,utils}/` | Layer implementations | +| `src/lib/implementations/{business,data,utils}/` | Layer implementations (`CircleProvider` for AppKit onramp) | | `src/assets/` | Static media only (SVGs, images) | Test Host Layer: `host/` (`npm run dev:host`). Style via Host RPC `setStyle`, not in-wallet debug knobs. +Fiat onramp: Asset Details **Buy** and host RPC `onramp({ chainId?, amount? })` open `OnrampView` (Circle AppKit). Sessions come from Relayer `POST /wallet/onramp` — never put the Circle kit key in this SPA. Default UI is `mountIframe`; for local/ngrok before Circle CSP allowlisting, set `localStorage.circlePopup = "true"` to use `openWindow` (prefetch session, then a sync click). Cloudsmith: set `CLOUDSMITH_TOKEN` before `npm install` (see README). + ### Form validation UX Primary submit actions (e.g. Send in `TransferTokensModal`) stay **disabled until every required field is valid**. Do not leave the button enabled and only reject on click. Empty fields show no error text; invalid non-empty input shows inline errors; the CTA enables only when the whole form is ready. diff --git a/Dockerfile b/Dockerfile index 0083a63..143f5e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,13 @@ WORKDIR /app COPY package.json package-lock.json ./ COPY host/package.json ./host/ -RUN npm ci +COPY .npmrc ./ + +# Circle @crcl-main/* requires CLOUDSMITH_TOKEN BuildKit secret +RUN --mount=type=secret,id=cloudsmith_token \ + CLOUDSMITH_TOKEN="$(cat /run/secrets/cloudsmith_token)" \ + npm ci \ + && rm -f .npmrc COPY index.html vite.config.ts tsconfig.json tsconfig.node.json components.json ./ COPY src ./src diff --git a/README.md b/README.md index c5cd481..f0931d8 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,36 @@ Production deliverable: a static **nginx** Docker image (no server-side runtime) ## Setup +Circle’s private AppKit canary requires Cloudsmith auth. The repo includes `.npmrc`; +export your token before installing: + +```bash +# Linux / macOS +export CLOUDSMITH_TOKEN= +``` + +```powershell +# Windows PowerShell +$env:CLOUDSMITH_TOKEN = "" +``` + +CI Docker builds expect GitHub Actions secret `CLOUDSMITH_TOKEN`. + ```bash npm install cp .env.example .env # set NGROK_AUTHTOKEN (and optional NGROK_DOMAIN) ``` +Fiat onramp uses Circle AppKit (`Buy` in Asset Details, or host RPC `onramp`). +Sessions are minted by the Relayer (`POST /wallet/onramp`); the kit key never +ships in this SPA. Inline iframe onramp requires your wallet domain to be +registered with Circle for CSP — see Circle’s beta docs. For local/ngrok +testing before CSP allowlisting, force the popup flow: + +```js +localStorage.setItem("circlePopup", "true") +``` + ## Develop ```bash diff --git a/host/src/components/WalletActions.tsx b/host/src/components/WalletActions.tsx index f6ff06d..1c093b5 100644 --- a/host/src/components/WalletActions.tsx +++ b/host/src/components/WalletActions.tsx @@ -47,6 +47,7 @@ export interface IWalletActionsProps { onUnfocusWallet: () => void; onAddUsdcArc: () => void; onAddUsdtBase: () => void; + onOnramp: () => void; } export function WalletActions({ @@ -78,6 +79,7 @@ export function WalletActions({ onUnfocusWallet, onAddUsdcArc, onAddUsdtBase, + onOnramp, }: IWalletActionsProps) { const meta = hostChainMeta(chainId); @@ -310,6 +312,24 @@ export function WalletActions({ + +
+ +

+ Open Circle fiat onramp via onramp (Buy crypto into the + unlocked wallet address). +

+
+ +
+
); } diff --git a/host/src/hooks/useHostTestActions.ts b/host/src/hooks/useHostTestActions.ts index d1d6bb4..4a30d2c 100644 --- a/host/src/hooks/useHostTestActions.ts +++ b/host/src/hooks/useHostTestActions.ts @@ -481,6 +481,28 @@ export function useHostTestActions({ })(); }; + const handleOnramp = () => { + const proxy = proxyRef.current; + if (!proxy) return; + setBusy(true); + reportStatus("Opening onramp…"); + void (async () => { + try { + await proxy.rpc("onramp", {}); + proxy.showWallet(); + setWalletVisible(true); + reportStatus("Onramp closed."); + } catch (error) { + reportStatus( + error instanceof Error ? error.message : "onramp failed", + true, + ); + } finally { + setBusy(false); + } + })(); + }; + const walletActionProps = { ready, busy, @@ -510,6 +532,7 @@ export function useHostTestActions({ onUnfocusWallet: handleUnfocusWallet, onAddUsdcArc: handleAddUsdcArc, onAddUsdtBase: handleAddUsdtBase, + onOnramp: handleOnramp, }; return { diff --git a/package-lock.json b/package-lock.json index c0b2e1c..aa8e059 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@1shotapi/ows-signer-utils": "^0.4.0", "@1shotapi/ows-types": "^0.2.4", "@1shotapi/ows-wallet-utils": "^0.2.0", + "@crcl-main/app-kit": "^1.10.0-canary-feature-onramp-kit-sdk.1784835391", "@fontsource-variable/geist": "^5.2.9", "@metamask/smart-accounts-kit": "^1.7.0", "@simplewebauthn/browser": "^13.3.0", @@ -646,6 +647,15 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", @@ -769,6 +779,544 @@ "win32" ] }, + "node_modules/@coral-xyz/anchor": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/anchor/-/anchor-0.31.1.tgz", + "integrity": "sha512-QUqpoEK+gi2S6nlYc2atgT2r41TT3caWr/cPUEL8n8Md9437trZ68STknq897b82p5mW0XrTBNOzRbmIRJtfsA==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@coral-xyz/anchor-errors": "^0.31.1", + "@coral-xyz/borsh": "^0.31.1", + "@noble/hashes": "^1.3.1", + "@solana/web3.js": "^1.69.0", + "bn.js": "^5.1.2", + "bs58": "^4.0.1", + "buffer-layout": "^1.2.2", + "camelcase": "^6.3.0", + "cross-fetch": "^3.1.5", + "eventemitter3": "^4.0.7", + "pako": "^2.0.3", + "superstruct": "^0.15.4", + "toml": "^3.0.0" + }, + "engines": { + "node": ">=17" + } + }, + "node_modules/@coral-xyz/anchor-errors": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/anchor-errors/-/anchor-errors-0.31.1.tgz", + "integrity": "sha512-NhNEku4F3zzUSBtrYz84FzYWm48+9OvmT1Hhnwr6GnPQry2dsEqH/ti/7ASjjpoFTWRnPXrjAIT1qM6Isop+LQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/@coral-xyz/borsh": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.31.1.tgz", + "integrity": "sha512-9N8AU9F0ubriKfNE3g1WF0/4dtlGXoBN/hd1PvbNBamBNwRgHxH4P+o3Zt7rSEloW1HUs6LfZEchlx9fW7POYw==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@solana/web3.js": "^1.69.0" + } + }, + "node_modules/@crcl-main/app-kit": { + "version": "1.10.0-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/app-kit/-/app-kit-1.10.0-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-FfLR6nr/HmqaqSs7ZtCL4jmJzhF4sL+ru0oHGbtO+lcbb3TYBy5vYeuyYgWHQl79e4hCmJUN3xYw20l8PT5MVA==", + "dependencies": { + "@coral-xyz/anchor": "^0.31.1", + "@crcl-main/bridge-kit": "1.12.1-canary-feature-onramp-kit-sdk.1784835391", + "@crcl-main/earn-kit": "1.3.0-canary-feature-onramp-kit-sdk.1784835391", + "@crcl-main/onramp-kit": "0.0.1-canary-feature-onramp-kit-sdk.1784835391", + "@crcl-main/provider-gateway-v1": "1.1.3-canary-feature-onramp-kit-sdk.1784835391", + "@crcl-main/swap-kit": "1.4.0-canary-feature-onramp-kit-sdk.1784835391", + "@crcl-main/unified-balance-kit": "1.3.0-canary-feature-onramp-kit-sdk.1784835391", + "@ethersproject/abi": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/units": "^5.8.0", + "@noble/curves": "1.4.2", + "@solana/web3.js": "^1.98.4", + "abitype": "^1.1.0", + "bn.js": "^5.2.3", + "bs58": "6.0.0", + "buffer": "^6.0.3", + "pino": "10.1.0", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@crcl-main/app-kit/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/app-kit/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/app-kit/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@crcl-main/bridge-kit": { + "version": "1.12.1-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/bridge-kit/-/bridge-kit-1.12.1-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-z59Mus6FOdFJloXNi5hkzKwHjDFdblave8+e5sDqrDy6tqNBu2aq7uez3vjMfvnqRu5elaBEAAASonm8jQeyGQ==", + "dependencies": { + "@crcl-main/provider-cctp-v2": "1.10.0-canary-feature-onramp-kit-sdk.1784835391", + "@ethersproject/abi": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/units": "^5.8.0", + "@solana/web3.js": "^1.98.4", + "abitype": "^1.1.0", + "bs58": "6.0.0", + "pino": "10.1.0", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@crcl-main/bridge-kit/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@crcl-main/earn-kit": { + "version": "1.3.0-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/earn-kit/-/earn-kit-1.3.0-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-IBcDCDN32X3Jy28SP9e5XC8TbJ/UgzBqn8dA/9cAH7ttA0tyCeZTPwMiLXeNI0nHQ5zrJTTY1Sw3latGAFWn/A==", + "dependencies": { + "@crcl-main/provider-earn-service": "1.3.0-canary-feature-onramp-kit-sdk.1784835391", + "@ethersproject/abi": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/units": "^5.8.0", + "@solana/web3.js": "^1.98.4", + "abitype": "^1.1.0", + "bs58": "6.0.0", + "pino": "10.1.0", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@crcl-main/earn-kit/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@crcl-main/onramp-kit": { + "version": "0.0.1-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/onramp-kit/-/onramp-kit-0.0.1-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-72nyxHll7kEMcbL/U3scA39njcVpDQCVfCEQ6EcH+7E964/63m0fHEHfPFmvnNjph5Abneqq32dOsbKlWeYzFg==", + "dependencies": { + "pino": "10.1.0", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@crcl-main/onramp-kit/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@crcl-main/provider-cctp-v2": { + "version": "1.10.0-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-cctp-v2/-/provider-cctp-v2-1.10.0-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-232LEFAViDGzIhpC9rD7yiREc1MmvexErEh1lQ/5lkax08/qTULWwi6O70GhMtfIKq9AB0rV8OnpC5GsY4UCeQ==", + "dependencies": { + "@coral-xyz/anchor": "^0.31.1", + "@ethersproject/abi": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/units": "^5.8.0", + "@noble/curves": "1.4.2", + "@solana/web3.js": "^1.98.4", + "abitype": "^1.1.0", + "bs58": "6.0.0", + "buffer": "^6.0.3", + "pino": "10.1.0", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@solana/web3.js": "^1.98.2" + }, + "peerDependenciesMeta": { + "@solana/web3.js": { + "optional": true + } + } + }, + "node_modules/@crcl-main/provider-cctp-v2/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/provider-cctp-v2/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/provider-cctp-v2/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@crcl-main/provider-earn-service": { + "version": "1.3.0-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-earn-service/-/provider-earn-service-1.3.0-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-93TzDgvhFMXBn/DOOB0XE0LKg2NGsmn4nfuJhlrpTdtuYVzvRANPthdv7gooDL1St3EfOxnh68gt5YkJlcrBnQ==", + "dependencies": { + "@ethersproject/abi": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/units": "^5.8.0", + "@solana/web3.js": "^1.98.4", + "abitype": "^1.1.0", + "bs58": "6.0.0", + "pino": "10.1.0", + "viem": "^2.30.0", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@crcl-main/provider-earn-service/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@crcl-main/provider-gateway-v1": { + "version": "1.1.3-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-gateway-v1/-/provider-gateway-v1-1.1.3-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-KoDN0Fh1qSt9URuc+/pAEc3szHvB2zk1fNuFgKh6yTAwI70G4orNivo7GpWp6OkPq7vboxpGXvLW0ptepi6KyQ==", + "dependencies": { + "@coral-xyz/anchor": "^0.31.1", + "@ethersproject/abi": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/units": "^5.8.0", + "@noble/curves": "1.4.2", + "@solana/web3.js": "^1.98.4", + "abitype": "^1.1.0", + "bn.js": "^5.2.3", + "bs58": "6.0.0", + "buffer": "^6.0.3", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@crcl-main/provider-gateway-v1/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/provider-gateway-v1/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/provider-gateway-v1/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@crcl-main/provider-stablecoin-service-swap": { + "version": "1.3.0-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-stablecoin-service-swap/-/provider-stablecoin-service-swap-1.3.0-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-DcE2yoS7CPbsmkbJpX+QMoLVSjMPrXkQub8xNVN+YzKxKPwHmKwLN5naQ6QV5Te6soxbMUPOBpHqkDo/yKO/lA==", + "dependencies": { + "@coral-xyz/anchor": "^0.31.1", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/units": "^5.8.0", + "@noble/curves": "1.4.2", + "@solana/web3.js": "^1.98.4", + "abitype": "^1.1.0", + "bn.js": "^5.2.3", + "bs58": "^6.0.0", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@crcl-main/provider-stablecoin-service-swap/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/provider-stablecoin-service-swap/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/provider-stablecoin-service-swap/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@crcl-main/swap-kit": { + "version": "1.4.0-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/swap-kit/-/swap-kit-1.4.0-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-MWDSp2iJ5aMSer+mlRiDPteqUo9QLNY/krQGS4ZlaEz5ndf7ceGCtBjHdNh7Yf1Fp828BYBoQQE1EFcNk13ALA==", + "dependencies": { + "@coral-xyz/anchor": "^0.31.1", + "@crcl-main/provider-stablecoin-service-swap": "1.3.0-canary-feature-onramp-kit-sdk.1784835391", + "@ethersproject/abi": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/units": "^5.8.0", + "@noble/curves": "1.4.2", + "@solana/web3.js": "^1.98.4", + "abitype": "^1.1.0", + "bn.js": "^5.2.3", + "bs58": "6.0.0", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@crcl-main/swap-kit/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/swap-kit/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/swap-kit/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@crcl-main/unified-balance-kit": { + "version": "1.3.0-canary-feature-onramp-kit-sdk.1784835391", + "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/unified-balance-kit/-/unified-balance-kit-1.3.0-canary-feature-onramp-kit-sdk.1784835391.tgz", + "integrity": "sha512-OX19leoAPWlSygx75jbROHZahcMI6y27wlUaBdaCe1IeUHgGM1YrqGuLngmC1eTGC5fmA4Sl+SrJ4v5HrVKpCQ==", + "dependencies": { + "@coral-xyz/anchor": "^0.31.1", + "@crcl-main/provider-gateway-v1": "1.1.3-canary-feature-onramp-kit-sdk.1784835391", + "@ethersproject/abi": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/units": "^5.8.0", + "@noble/curves": "1.4.2", + "@solana/web3.js": "^1.98.4", + "abitype": "^1.1.0", + "bn.js": "^5.2.3", + "bs58": "6.0.0", + "zod": "3.25.67" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@crcl-main/unified-balance-kit/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/unified-balance-kit/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@crcl-main/unified-balance-kit/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/@dotenvx/dotenvx": { "version": "1.75.1", "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.75.1.tgz", @@ -1559,49 +2107,462 @@ "integrity": "sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==", "license": "MIT", "dependencies": { - "@ethereumjs/util": "^8.1.0", - "crc-32": "^1.2.0" + "@ethereumjs/util": "^8.1.0", + "crc-32": "^1.2.0" + } + }, + "node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethereumjs/tx": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-4.2.0.tgz", + "integrity": "sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/common": "^3.2.0", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.1.0", + "ethereum-cryptography": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethersproject/abi": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.8.0.tgz", + "integrity": "sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz", + "integrity": "sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/networks": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/web": "^5.8.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz", + "integrity": "sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.8.0.tgz", + "integrity": "sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/rlp": "^5.8.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.8.0.tgz", + "integrity": "sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.8.0.tgz", + "integrity": "sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz", + "integrity": "sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.8.0.tgz", + "integrity": "sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.8.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.8.0.tgz", + "integrity": "sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/base64": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.8.0.tgz", + "integrity": "sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz", + "integrity": "sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" + }, + "node_modules/@ethersproject/networks": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.8.0.tgz", + "integrity": "sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.8.0.tgz", + "integrity": "sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.8.0.tgz", + "integrity": "sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.8.0.tgz", + "integrity": "sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "bn.js": "^5.2.1", + "elliptic": "6.6.1", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.8.0.tgz", + "integrity": "sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, - "node_modules/@ethereumjs/rlp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", - "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", - "license": "MPL-2.0", - "bin": { - "rlp": "bin/rlp" - }, - "engines": { - "node": ">=14" + "node_modules/@ethersproject/transactions": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.8.0.tgz", + "integrity": "sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/rlp": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0" } }, - "node_modules/@ethereumjs/tx": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-4.2.0.tgz", - "integrity": "sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==", - "license": "MPL-2.0", + "node_modules/@ethersproject/units": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.8.0.tgz", + "integrity": "sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "@ethereumjs/common": "^3.2.0", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.1.0", - "ethereum-cryptography": "^2.0.0" - }, - "engines": { - "node": ">=14" + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, - "node_modules/@ethereumjs/util": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", - "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", - "license": "MPL-2.0", + "node_modules/@ethersproject/web": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.8.0.tgz", + "integrity": "sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "@ethereumjs/rlp": "^4.0.1", - "ethereum-cryptography": "^2.0.0", - "micro-ftch": "^0.3.1" - }, - "engines": { - "node": ">=14" + "@ethersproject/base64": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@floating-ui/core": { @@ -3398,6 +4359,12 @@ "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", + "license": "MIT" + }, "node_modules/@radix-ui/number": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.2.tgz", @@ -5455,6 +6422,127 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", + "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "license": "MIT", + "dependencies": { + "buffer": "~6.0.3" + }, + "engines": { + "node": ">=5.10" + } + }, + "node_modules/@solana/codecs-core": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz", + "integrity": "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/codecs-numbers": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz", + "integrity": "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/errors": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz", + "integrity": "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^14.0.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/web3.js": { + "version": "1.98.4", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.4.tgz", + "integrity": "sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@noble/curves": "^1.4.2", + "@noble/hashes": "^1.4.0", + "@solana/buffer-layout": "^4.0.1", + "@solana/codecs-numbers": "^2.1.0", + "agentkeepalive": "^4.5.0", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.3", + "fast-stable-stringify": "^1.0.0", + "jayson": "^4.1.1", + "node-fetch": "^2.7.0", + "rpc-websockets": "^9.0.2", + "superstruct": "^2.0.2" + } + }, + "node_modules/@solana/web3.js/node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/@solana/web3.js/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/@solana/web3.js/node_modules/superstruct": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz", + "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@tailwindcss/node": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.2.tgz", @@ -5827,6 +6915,15 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.13", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", @@ -5874,7 +6971,6 @@ "version": "22.20.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -5910,12 +7006,27 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "license": "MIT" + }, "node_modules/@types/validate-npm-package-name": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/validate-npm-package-name/-/validate-npm-package-name-4.0.2.tgz", "integrity": "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==", "license": "MIT" }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/types": { "version": "8.65.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.65.0.tgz", @@ -6028,6 +7139,18 @@ "agent-install": "bin/agent-install.mjs" } }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/ajv": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", @@ -6150,6 +7273,15 @@ "astring": "bin/astring" } }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/atomically": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", @@ -6181,6 +7313,32 @@ "node": "18 || 20 || >=22" } }, + "node_modules/base-x": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz", + "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.10.43", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.43.tgz", @@ -6193,6 +7351,12 @@ "node": ">=6.0.0" } }, + "node_modules/bn.js": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.5.tgz", + "integrity": "sha512-Vq886eXykuP5E6HcKSSStP3bJgrE6In5WKxVUvJ8XGpWWYs2xZHWqUwzCtGgEtBcxyd57KBFDPFoUfNzdaHCNg==", + "license": "MIT" + }, "node_modules/body-parser": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", @@ -6230,6 +7394,35 @@ "url": "https://opencollective.com/express" } }, + "node_modules/borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "node_modules/borsh/node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/borsh/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, "node_modules/brace-expansion": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", @@ -6254,6 +7447,12 @@ "node": ">=8" } }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" + }, "node_modules/browserslist": { "version": "4.28.6", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.6.tgz", @@ -6287,6 +7486,62 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "license": "MIT", + "dependencies": { + "base-x": "^5.0.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-layout": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", + "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==", + "license": "MIT", + "engines": { + "node": ">=4.5" + } + }, + "node_modules/bufferutil": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.1.0.tgz", + "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/bundle-name": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", @@ -6806,6 +8061,15 @@ "node": ">=0.8" } }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -6972,6 +8236,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -7081,6 +8357,27 @@ "integrity": "sha512-YmCu4856jkgKT1Nh6fwRdeVrM6Ydf/fBnq51tpmSfX+jOcUMTxh31yH6hjKScRenhB2oDSvA9oooxcpjogPeig==", "license": "ISC" }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.5", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.5.tgz", + "integrity": "sha512-3aRg6/JxfffFD+OlOjOFR3Vo79l39ooBTFucxx+MT3dhCtzn3EmiUPQo+6/OZuI2jbXi3YKgmiTFBgChQMwIRQ==", + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", @@ -7197,10 +8494,25 @@ "integrity": "sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==", "dev": true, "license": "MIT", - "workspaces": [ - "docs", - "benchmarks" - ] + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "license": "MIT" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "license": "MIT", + "dependencies": { + "es6-promise": "^4.0.3" + } }, "node_modules/esbuild": { "version": "0.28.1", @@ -7779,6 +9091,14 @@ "express": ">= 4.11" } }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -7817,6 +9137,12 @@ "license": "MIT", "peer": true }, + "node_modules/fast-stable-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", + "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==", + "license": "MIT" + }, "node_modules/fast-uri": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", @@ -8164,6 +9490,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", @@ -8193,6 +9529,17 @@ "hermes-estree": "0.25.1" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/hono": { "version": "4.12.30", "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.30.tgz", @@ -8231,6 +9578,15 @@ "node": ">=18.18.0" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", @@ -8247,6 +9603,26 @@ "url": "https://opencollective.com/express" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -8724,6 +10100,15 @@ "node": ">=18" } }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, "node_modules/isows": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", @@ -8739,6 +10124,90 @@ "ws": "*" } }, + "node_modules/jayson": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.3.0.tgz", + "integrity": "sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==", + "license": "MIT", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "stream-json": "^1.9.1", + "uuid": "^8.3.2", + "ws": "^7.5.10" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "license": "MIT" + }, + "node_modules/jayson/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/jayson/node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/jayson/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "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).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/jayson/node_modules/ws": { + "version": "7.5.13", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.13.tgz", + "integrity": "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/jiti": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", @@ -8758,6 +10227,12 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -8832,6 +10307,12 @@ "license": "MIT", "peer": true }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9384,6 +10865,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" + }, "node_modules/minimatch": { "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", @@ -9456,6 +10949,38 @@ "node": ">= 0.6" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-gyp-build-optional-packages": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz", @@ -9538,6 +11063,15 @@ "node": ">= 10" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -10016,6 +11550,43 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pino": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.1.0.tgz", + "integrity": "sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", + "license": "MIT" + }, "node_modules/pkce-challenge": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", @@ -10140,6 +11711,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -10239,6 +11826,12 @@ ], "license": "MIT" }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, "node_modules/radix-ui": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.6.2.tgz", @@ -10609,6 +12202,15 @@ } } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/recast": { "version": "0.23.12", "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.12.tgz", @@ -10774,6 +12376,51 @@ "node": ">= 18" } }, + "node_modules/rpc-websockets": { + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.9.tgz", + "integrity": "sha512-2iQDaTB4g5fDB2ihrTFSJSibCEuxaRi1q7qTW7ZO9/M5/TC+ToHA4D9/ffNLEbAoHNNrcdeP05oATNk44SKZXA==", + "license": "LGPL-3.0-only", + "dependencies": { + "@swc/helpers": "^0.5.11", + "@types/uuid": "^10.0.0", + "@types/ws": "^8.2.2", + "buffer": "^6.0.3", + "eventemitter3": "^5.0.1", + "uuid": "^14.0.0", + "ws": "^8.5.0" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^6.0.0" + } + }, + "node_modules/rpc-websockets/node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/rpc-websockets/node_modules/uuid": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", + "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, "node_modules/run-applescript": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", @@ -10809,6 +12456,35 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -11106,6 +12782,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sonic-boom": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", + "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -11124,6 +12809,15 @@ "node": ">=0.10.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -11168,6 +12862,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", + "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, "node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", @@ -11291,6 +13000,12 @@ "dev": true, "license": "MIT" }, + "node_modules/superstruct": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.15.5.tgz", + "integrity": "sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==", + "license": "MIT" + }, "node_modules/systeminformation": { "version": "5.31.17", "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.17.tgz", @@ -11374,6 +13089,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, + "node_modules/thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -11418,6 +13147,18 @@ "node": ">=0.6" } }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "license": "MIT" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/ts-brand": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/ts-brand/-/ts-brand-0.2.0.tgz", @@ -11529,7 +13270,6 @@ "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -11565,7 +13305,6 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, "license": "MIT" }, "node_modules/unicorn-magic": { @@ -11682,6 +13421,20 @@ } } }, + "node_modules/utf-8-validate": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz", + "integrity": "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -11880,6 +13633,22 @@ "dev": true, "license": "MIT" }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/when-exit": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.5.tgz", diff --git a/package.json b/package.json index 9aabf7a..5e49227 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "clean": "node scripts/clean.mjs && npm run clean -w @1shotapi/oneshot-wallet-host", "lint": "tsc -p tsconfig.json --noEmit", "preview": "vite preview", - "dockerize": "docker build -t oneshot-wallet .", + "dockerize": "docker build --secret id=cloudsmith_token,env=CLOUDSMITH_TOKEN -t oneshot-wallet .", "doctor": "npx react-doctor@latest" }, "dependencies": { @@ -26,6 +26,7 @@ "@1shotapi/ows-signer-utils": "^0.4.0", "@1shotapi/ows-types": "^0.2.4", "@1shotapi/ows-wallet-utils": "^0.2.0", + "@crcl-main/app-kit": "^1.10.0-canary-feature-onramp-kit-sdk.1784835391", "@fontsource-variable/geist": "^5.2.9", "@metamask/smart-accounts-kit": "^1.7.0", "@simplewebauthn/browser": "^13.3.0", diff --git a/skills/oneshot-embedded-wallet/SKILL.md b/skills/oneshot-embedded-wallet/SKILL.md index b9db67e..9c8d8ea 100644 --- a/skills/oneshot-embedded-wallet/SKILL.md +++ b/skills/oneshot-embedded-wallet/SKILL.md @@ -3,7 +3,7 @@ name: oneshot-embedded-wallet description: >- Integrate the 1Shot embedded wallet (OWS Host Layer) with @1shotapi/ows-provider. Use when embedding wallet.1shotapi.com, wiring OWSProxy, EIP-1193, credentials, - or custom RPC such as setStyle / focusWallet / addAsset / createAccount for + or custom RPC such as setStyle / focusWallet / addAsset / createAccount / onramp for theming, host-driven focus mode, tracked assets, and first-party Safari create. license: MIT metadata: @@ -232,7 +232,7 @@ Users can also add assets from the Balances tab without a host RPC. The Balances ## Custom RPC — `createAccount` -Used by the first-party **`/create/`** host page (Safari passkey create). Hosts embedding the wallet normally do **not** call this — the branding layer opens `/create/` itself when needed. +Used by the first-party **`/create/`** host page (Safari passkey create). Hosts embedding the wallet normally do **not** call this — the branding layer opens `/create/` itself when needed. Not exposed as a playground button. ```typescript const result = await proxy.rpc("createAccount"); @@ -246,6 +246,24 @@ await proxy.rpc("createAccount", { accountName: "My Wallet" }); |--------|--------|--------| | `createAccount` | `{ accountName?: string }` optional | Runs setup create (passkey + relayer register); returns credential id | +## Custom RPC — `onramp` + +Opens Circle fiat onramp fullscreen inside the Branding Layer for the unlocked EVM address. + +```typescript +await proxy.rpc("onramp", { + chainId: 8453, // optional — decimal chain id for catalog scoping + amount: "50", // optional — amount hint when supported by the kit +}); +// or: await proxy.rpc("onramp", {}); +``` + +| Method | Params | Behavior | +|--------|--------|----------| +| `onramp` | `{ chainId?: number, amount?: string }` | Shows wallet, mounts Circle AppKit onramp; session minted via Relayer `POST /wallet/onramp` | + +Returns `{ ok: true }` when the user closes the onramp view. The Relayer holds the Circle kit key; the browser only receives a single-use session. Inline iframe requires Circle CSP allowlisting of the wallet origin; for local/ngrok testing the branding layer honors `localStorage.setItem("circlePopup", "true")` and uses AppKit `openWindow` instead. + ## Other Host APIs | API | Use | @@ -253,7 +271,7 @@ await proxy.rpc("createAccount", { accountName: "My Wallet" }); | `proxy.ethereum.request(...)` | EIP-1193 (accounts, sign, chain, …) | | `proxy.credentials.*` | OID4 offer / present (when enabled in wallet) | | `proxy.showWallet()` / `hideWallet()` | Host-driven flyout without an EIP-1193 call | -| `proxy.rpc(method, params)` | Custom Branding RPC (`setStyle`, `focusWallet`, `unfocusWallet`, `addAsset`, `createAccount`, …) | +| `proxy.rpc(method, params)` | Custom Branding RPC (`setStyle`, `focusWallet`, `unfocusWallet`, `addAsset`, `createAccount`, `onramp`, …) | ## Hard rules @@ -262,3 +280,4 @@ await proxy.rpc("createAccount", { accountName: "My Wallet" }); - Theme with `setStyle`; do not ask integrators to fork CSS for basic brand colors / product name. - Use `focusWallet` / `unfocusWallet` for host-driven single-asset flows; do not expose mode switching in the wallet UI. - Use `addAsset` when the host wants a lasting Balances entry; expect a confirm modal (contrast with `focusWallet`). +- Use `onramp` (or the in-wallet Buy button) for fiat → crypto; do not put the Circle kit key in the Host or Branding Layer. diff --git a/src/circle/CircleContext.tsx b/src/circle/CircleContext.tsx new file mode 100644 index 0000000..bff0537 --- /dev/null +++ b/src/circle/CircleContext.tsx @@ -0,0 +1,30 @@ +import { + createContext, + useContext, + useMemo, + type ReactNode, +} from "react"; +import type { ICircleProvider } from "../lib/interfaces/utils/ICircleProvider"; + +const CircleContext = createContext(null); + +export function CircleContextProvider({ + provider, + children, +}: { + provider: ICircleProvider; + children: ReactNode; +}) { + const value = useMemo(() => provider, [provider]); + return ( + {children} + ); +} + +export function useCircle(): ICircleProvider { + const ctx = useContext(CircleContext); + if (!ctx) { + throw new Error("useCircle must be used within CircleContextProvider"); + } + return ctx; +} diff --git a/src/circle/circleChains.ts b/src/circle/circleChains.ts new file mode 100644 index 0000000..8c7b4c2 --- /dev/null +++ b/src/circle/circleChains.ts @@ -0,0 +1,39 @@ +/** Map EVM decimal chain id → Circle onramp chain label (`Blockchain` enum). */ +const CIRCLE_CHAIN_BY_DECIMAL: ReadonlyMap = new Map([ + [1, "Ethereum"], + [10, "Optimism"], + [137, "Polygon"], + [8453, "Base"], + [42161, "Arbitrum"], + [43114, "Avalanche"], + [59144, "Linea"], + [130, "Unichain"], +]); + +/** + * Convert a hex (`0x…`) or decimal chain id to Circle's display chain label. + * Returns null when unsupported (widget shows full catalog). + */ +export function circleChainLabelFromChainId( + chainId: string | number | bigint, +): string | null { + let decimal: number; + if (typeof chainId === "number") { + decimal = chainId; + } else if (typeof chainId === "bigint") { + decimal = Number(chainId); + } else { + const trimmed = chainId.trim(); + if (/^0x[0-9a-fA-F]+$/i.test(trimmed)) { + decimal = Number(BigInt(trimmed)); + } else if (/^\d+$/.test(trimmed)) { + decimal = Number(trimmed); + } else { + return null; + } + } + if (!Number.isFinite(decimal)) { + return null; + } + return CIRCLE_CHAIN_BY_DECIMAL.get(decimal) ?? null; +} diff --git a/src/circle/circlePopup.ts b/src/circle/circlePopup.ts new file mode 100644 index 0000000..0da9123 --- /dev/null +++ b/src/circle/circlePopup.ts @@ -0,0 +1,17 @@ +/** Dev override key: `localStorage.setItem("circlePopup", "true")`. */ +export const CIRCLE_POPUP_STORAGE_KEY = "circlePopup"; + +/** + * When true, onramp uses AppKit `openWindow` instead of `mountIframe`. + * Needed for local/ngrok hosts that are not yet on Circle’s iframe CSP allowlist. + */ +export function isCirclePopupPreferred(): boolean { + try { + return ( + typeof localStorage !== "undefined" && + localStorage.getItem(CIRCLE_POPUP_STORAGE_KEY) === "true" + ); + } catch { + return false; + } +} diff --git a/src/circle/onrampTypes.ts b/src/circle/onrampTypes.ts new file mode 100644 index 0000000..5c2b61d --- /dev/null +++ b/src/circle/onrampTypes.ts @@ -0,0 +1,9 @@ +import type { EVMAccountAddress } from "@1shotapi/ows-types"; + +/** Params for opening the Circle onramp fullscreen view. */ +export type IOnrampOpenRequest = { + destinationAddress: EVMAccountAddress; + chainId?: number; + amount?: string; + tokenSymbol?: string; +}; diff --git a/src/circle/openOnramp.ts b/src/circle/openOnramp.ts new file mode 100644 index 0000000..6d1fc82 --- /dev/null +++ b/src/circle/openOnramp.ts @@ -0,0 +1,13 @@ +import { pushModal } from "../wallet/pushModal"; +import type { IOnrampOpenRequest } from "./onrampTypes"; + +/** Open the shared fullscreen Circle onramp (Buy + host `onramp` RPC). */ +export function openOnramp(request: IOnrampOpenRequest): Promise { + return pushModal(({ id, resolve, reject }) => ({ + id, + kind: "onramp", + request, + resolve, + reject, + })); +} diff --git a/src/components/AssetDetails.tsx b/src/components/AssetDetails.tsx index 249accc..feedf07 100644 --- a/src/components/AssetDetails.tsx +++ b/src/components/AssetDetails.tsx @@ -13,10 +13,10 @@ import { useWallet } from "../wallet/WalletProvider"; import { resolveActiveAddress } from "../wallet/activeAddress"; import { useLiveTrackedBalance } from "../wallet/useLiveTrackedBalance"; import { useWalletSessionStore } from "../wallet/sessionStore"; +import { openOnramp } from "../circle/openOnramp"; import { BalanceDisplay } from "./BalanceDisplay"; import { TransactionHistory } from "./TransactionHistory"; import { ReceiveModal } from "./modals/ReceiveModal"; -import { PurchaseComingSoonModal } from "./modals/PurchaseComingSoonModal"; import { TransferTokensModal } from "./modals/TransferTokensModal"; export interface IAssetDetailsProps { @@ -39,7 +39,7 @@ export function AssetDetails({ asset: assetProp }: IAssetDetailsProps) { ); const [receiveOpen, setReceiveOpen] = useState(false); const [sendOpen, setSendOpen] = useState(false); - const [purchaseOpen, setPurchaseOpen] = useState(false); + const [buyBusy, setBuyBusy] = useState(false); const { balance, decimals } = useLiveTrackedBalance( assetProp.id, @@ -72,12 +72,30 @@ export function AssetDetails({ asset: assetProp }: IAssetDetailsProps) { solanaAddress, }); const canSend = asset.type === EAssetType.Erc20; + const canBuy = + Boolean(evmAddress) && String(evmAddress).toLowerCase() !== "0x0"; const openSend = useCallback(() => { void requestBalanceRefresh(asset.id); setSendOpen(true); }, [asset.id, requestBalanceRefresh]); + const openBuy = useCallback(() => { + if (!evmAddress || buyBusy) return; + setBuyBusy(true); + void openOnramp({ + destinationAddress: evmAddress, + chainId: Number(BigInt(asset.chainId)), + tokenSymbol: asset.symbol, + }) + .catch(() => { + /* user closed or mint failed — OnrampView surfaces errors */ + }) + .finally(() => { + setBuyBusy(false); + }); + }, [asset.chainId, asset.symbol, buyBusy, evmAddress]); + return (
@@ -113,7 +131,8 @@ export function AssetDetails({ asset: assetProp }: IAssetDetailsProps) { setPurchaseOpen(true)} + disabled={!canBuy || buyBusy} + onClick={openBuy} > @@ -152,9 +171,6 @@ export function AssetDetails({ asset: assetProp }: IAssetDetailsProps) { }} /> ) : null} - {purchaseOpen ? ( - setPurchaseOpen(false)} /> - ) : null}
); } diff --git a/src/components/ModalHost.tsx b/src/components/ModalHost.tsx index ea4e6db..ec33ddb 100644 --- a/src/components/ModalHost.tsx +++ b/src/components/ModalHost.tsx @@ -19,6 +19,7 @@ import { ImportPrivateKeyModal } from "./modals/ImportPrivateKeyModal"; import { AdvancedOptionsModal } from "./modals/AdvancedOptionsModal"; import { AddAssetModal } from "./modals/AddAssetModal"; import { OpenCreateTabModal } from "./modals/OpenCreateTabModal"; +import { OnrampView } from "./OnrampView"; export function ModalHost() { const activeModal = useModalStore((state) => state.activeModal); @@ -114,6 +115,16 @@ export function ModalHost() { onResolve={activeModal.resolve} /> ); + case "onramp": + return ( + activeModal.resolve()} + /> + ); default: return null; } diff --git a/src/components/OnrampView.tsx b/src/components/OnrampView.tsx new file mode 100644 index 0000000..e78ac59 --- /dev/null +++ b/src/components/OnrampView.tsx @@ -0,0 +1,277 @@ +import { useEffect, useRef, useState } from "react"; +import type { + AppKitOnrampOperations, + OnrampSession, + OnrampWidget, +} from "@crcl-main/app-kit"; +import type { EVMAccountAddress } from "@1shotapi/ows-types"; +import { Modal, type ModalAction } from "./Modal"; +import { useCircle } from "../circle/CircleContext"; +import { circleChainLabelFromChainId } from "../circle/circleChains"; +import { isCirclePopupPreferred } from "../circle/circlePopup"; +import type { IOnrampOpenRequest } from "../circle/onrampTypes"; + +export type IOnrampViewProps = IOnrampOpenRequest & { + onClose: () => void; +}; + +/** + * Full-screen Circle AppKit onramp inside the Branding Layer shell. + * Default: inline iframe. With `localStorage.circlePopup === "true"`: popup + * window (session is prefetched; open must be a sync click — Circle requirement). + */ +export function OnrampView({ + destinationAddress, + chainId, + amount, + tokenSymbol, + onClose, +}: IOnrampViewProps) { + const circle = useCircle(); + const usePopup = isCirclePopupPreferred(); + const containerRef = useRef(null); + const widgetRef = useRef(null); + const onrampRef = useRef(null); + const sessionRef = useRef(null); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(true); + const [popupReady, setPopupReady] = useState(false); + const [popupOpened, setPopupOpened] = useState(false); + + useEffect(() => { + let cancelled = false; + const body = buildSessionBody({ + destinationAddress, + chainId, + amount, + tokenSymbol, + }); + + if (usePopup) { + void (async () => { + try { + const [onramp, url] = await Promise.all([ + circle.getOnramp(), + circle.getSessionUrl(), + ]); + if (cancelled) return; + onrampRef.current = onramp; + sessionRef.current = await onramp.fetchSession({ url, body }); + if (cancelled) return; + setLoading(false); + setPopupReady(true); + setError(null); + } catch (err: unknown) { + if (!cancelled) { + setLoading(false); + setPopupReady(false); + setError( + err instanceof Error ? err.message : "Failed to prepare onramp", + ); + } + } + })(); + + return () => { + cancelled = true; + widgetRef.current?.close(); + widgetRef.current = null; + onrampRef.current = null; + sessionRef.current = null; + }; + } + + const container = containerRef.current; + if (!container) { + return; + } + + void (async () => { + try { + const [onramp, url] = await Promise.all([ + circle.getOnramp(), + circle.getSessionUrl(), + ]); + if (cancelled) return; + + const mount = async () => { + const session = await onramp.fetchSession({ url, body }); + if (cancelled) return; + widgetRef.current?.close(); + widgetRef.current = onramp.mountIframe({ + session, + container, + onSessionExpired: () => { + void mount().catch((err: unknown) => { + if (!cancelled) { + setError( + err instanceof Error + ? err.message + : "Failed to refresh onramp session", + ); + } + }); + }, + }); + if (!cancelled) { + setLoading(false); + setError(null); + } + }; + + await mount(); + } catch (err: unknown) { + if (!cancelled) { + setLoading(false); + setError( + err instanceof Error ? err.message : "Failed to open onramp", + ); + } + } + })(); + + return () => { + cancelled = true; + widgetRef.current?.close(); + widgetRef.current = null; + }; + }, [amount, chainId, circle, destinationAddress, tokenSymbol, usePopup]); + + const openPopup = () => { + const onramp = onrampRef.current; + const session = sessionRef.current; + if (!onramp || !session) { + return; + } + + const result = onramp.openWindow({ + session, + onSessionExpired: () => { + setPopupOpened(false); + setPopupReady(false); + setLoading(true); + setError(null); + void (async () => { + try { + const url = await circle.getSessionUrl(); + const body = buildSessionBody({ + destinationAddress, + chainId, + amount, + tokenSymbol, + }); + sessionRef.current = await onramp.fetchSession({ url, body }); + setLoading(false); + setPopupReady(true); + } catch (err: unknown) { + setLoading(false); + setError( + err instanceof Error + ? err.message + : "Failed to refresh onramp session", + ); + } + })(); + }, + }); + + if (result.status === "blocked") { + setError(result.errorMessage); + setPopupOpened(false); + return; + } + + widgetRef.current?.close(); + widgetRef.current = result.widget; + setError(null); + setPopupOpened(true); + }; + + const actions: ModalAction[] = []; + if (usePopup && popupReady) { + actions.push({ + label: popupOpened ? "Reopen onramp" : "Open onramp", + onClick: openPopup, + variant: "primary", + }); + } + actions.push({ label: "Close", onClick: onClose, variant: "secondary" }); + + return ( + +
+ {error ? ( +

+ {error} +

+ ) : null} + {loading && !error ? ( +

+ {usePopup ? "Preparing onramp…" : "Loading onramp…"} +

+ ) : null} + {usePopup && popupReady && !popupOpened && !error ? ( +

+ Circle opens in a popup (local/ngrok CSP bypass). Click Open onramp + — browsers block popups after an async delay. +

+ ) : null} + {usePopup && popupOpened && !error ? ( +

+ Onramp opened in a popup. Complete the purchase there, then close + this dialog. +

+ ) : null} + {!usePopup ? ( +
+ ) : null} +
+ + ); +} + +function buildSessionBody(request: { + destinationAddress: EVMAccountAddress; + chainId?: number; + amount?: string; + tokenSymbol?: string; +}) { + const address = String(request.destinationAddress).toLowerCase(); + const chains: string[] = []; + const chainLabel = + request.chainId != null + ? circleChainLabelFromChainId(request.chainId) + : null; + if (chainLabel) { + chains.push(chainLabel); + } + + const tokens = + request.tokenSymbol && request.tokenSymbol.trim() + ? [request.tokenSymbol.trim().toUpperCase()] + : undefined; + + const assets = + chains.length > 0 || (tokens && tokens.length > 0) + ? { + ...(chains.length > 0 ? { chains } : {}), + ...(tokens && tokens.length > 0 ? { tokens } : {}), + } + : undefined; + + return { + userId: address, + destinationAddress: address, + ...(assets ? { assets } : {}), + ...(request.amount ? { amount: request.amount } : {}), + }; +} diff --git a/src/components/modals/PurchaseComingSoonModal.tsx b/src/components/modals/PurchaseComingSoonModal.tsx deleted file mode 100644 index f56ecb2..0000000 --- a/src/components/modals/PurchaseComingSoonModal.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { Modal } from "../Modal"; - -export interface IPurchaseComingSoonModalProps { - onClose: () => void; -} - -/** Placeholder until an onramp provider is integrated. */ -export function PurchaseComingSoonModal({ - onClose, -}: IPurchaseComingSoonModalProps) { - return ( - -

- Purchase capabilities coming soon -

-
- ); -} diff --git a/src/lib/implementations/utils/CircleProvider.ts b/src/lib/implementations/utils/CircleProvider.ts new file mode 100644 index 0000000..57c3194 --- /dev/null +++ b/src/lib/implementations/utils/CircleProvider.ts @@ -0,0 +1,42 @@ +import { AppKit } from "@crcl-main/app-kit"; +import type { ICircleProvider } from "../../interfaces/utils/ICircleProvider"; +import type { IConfigProvider } from "../../interfaces/utils/IConfigProvider"; + +/** + * Lazily constructs Circle {@link AppKit} and caches the onramp handle. + */ +export class CircleProvider implements ICircleProvider { + private kit: AppKit | null = null; + private onrampPromise: Promise | null = null; + + constructor(private readonly configProvider: IConfigProvider) {} + + async getOnramp(): Promise { + if (this.onrampPromise) { + return this.onrampPromise; + } + this.onrampPromise = this.createOnramp(); + try { + return await this.onrampPromise; + } catch (error) { + this.onrampPromise = null; + this.kit = null; + throw error; + } + } + + async getSessionUrl(): Promise { + const config = await this.configProvider.getConfig(); + return `${config.relayerBaseUrl.replace(/\/$/, "")}/wallet/onramp`; + } + + private async createOnramp(): Promise { + const config = await this.configProvider.getConfig(); + this.kit = new AppKit({ + onramp: { + widgetBaseUrl: config.onrampWidgetBaseUrl, + }, + }); + return this.kit.onramp; + } +} diff --git a/src/lib/implementations/utils/ConfigProvider.ts b/src/lib/implementations/utils/ConfigProvider.ts index fbb522c..8707c42 100644 --- a/src/lib/implementations/utils/ConfigProvider.ts +++ b/src/lib/implementations/utils/ConfigProvider.ts @@ -10,6 +10,8 @@ const DEFAULT_TRACKED_ASSETS_STORAGE_KEY = "ows.tracked-assets.v2"; const DEFAULT_CREDENTIALS_STORAGE_KEY = "ows.credentials.v2"; const DEFAULT_ASSET_ACTIVITY_LIMIT = 10; const DEFAULT_ASSET_ACTIVITY_MAX_OPTIMISTIC = 100; +const DEFAULT_ONRAMP_WIDGET_BASE_URL = + "https://onramp.arc.io/launch/onramp/v1"; /** * Resolves {@link WalletConfig} from the Branding Layer iframe host. @@ -30,6 +32,7 @@ export class ConfigProvider implements IConfigProvider { DEFAULT_CREDENTIALS_STORAGE_KEY, DEFAULT_ASSET_ACTIVITY_LIMIT, DEFAULT_ASSET_ACTIVITY_MAX_OPTIMISTIC, + DEFAULT_ONRAMP_WIDGET_BASE_URL, ); return this.cached; } diff --git a/src/lib/implementations/utils/index.ts b/src/lib/implementations/utils/index.ts index 9b7bd60..0204cae 100644 --- a/src/lib/implementations/utils/index.ts +++ b/src/lib/implementations/utils/index.ts @@ -1,4 +1,5 @@ export { ConfigProvider } from "./ConfigProvider"; +export { CircleProvider } from "./CircleProvider"; export { OWSProvider } from "./OWSProvider"; export { SupportedChainsBlockchainProvider } from "./SupportedChainsBlockchainProvider"; export { EventBus } from "./EventBus"; diff --git a/src/lib/interfaces/utils/ICircleProvider.ts b/src/lib/interfaces/utils/ICircleProvider.ts new file mode 100644 index 0000000..a1b43cf --- /dev/null +++ b/src/lib/interfaces/utils/ICircleProvider.ts @@ -0,0 +1,13 @@ +import type { AppKit } from "@crcl-main/app-kit"; + +/** + * Utility-level Circle AppKit lifecycle. Lazily constructs a single AppKit and + * exposes its onramp handle for OnrampView. + */ +export interface ICircleProvider { + getOnramp(): Promise; + /** Relayer session mint URL (`POST /wallet/onramp`). */ + getSessionUrl(): Promise; +} + +export const ICircleProviderType = Symbol.for("ICircleProvider"); diff --git a/src/lib/interfaces/utils/index.ts b/src/lib/interfaces/utils/index.ts index 650f3ea..2f72d66 100644 --- a/src/lib/interfaces/utils/index.ts +++ b/src/lib/interfaces/utils/index.ts @@ -1,5 +1,7 @@ export type { IConfigProvider } from "./IConfigProvider"; export { IConfigProviderType } from "./IConfigProvider"; +export type { ICircleProvider } from "./ICircleProvider"; +export { ICircleProviderType } from "./ICircleProvider"; export type { IEventBus } from "./IEventBus"; export { IEventBusType } from "./IEventBus"; export type { IOWSProvider } from "./IOWSProvider"; diff --git a/src/lib/types/domain/WalletConfig.ts b/src/lib/types/domain/WalletConfig.ts index 3d3c379..8d6aca9 100644 --- a/src/lib/types/domain/WalletConfig.ts +++ b/src/lib/types/domain/WalletConfig.ts @@ -16,5 +16,9 @@ export class WalletConfig { public readonly assetActivityDefaultLimit: number, /** Max optimistic send rows retained in localStorage. */ public readonly assetActivityMaxOptimistic: number, + /** + * Circle onramp widget origin (must match Relayer `ONRAMP_WIDGET_BASE_URL`). + */ + public readonly onrampWidgetBaseUrl: string, ) {} } diff --git a/src/wallet/WalletProvider.tsx b/src/wallet/WalletProvider.tsx index d6c69bd..4ec0904 100644 --- a/src/wallet/WalletProvider.tsx +++ b/src/wallet/WalletProvider.tsx @@ -37,6 +37,7 @@ import { OneshotRelayerRepository } from "../lib/implementations/data/OneshotRel import { TransactionService } from "../lib/implementations/business"; import { ConfigProvider, + CircleProvider, OWSProvider, SupportedChainsBlockchainProvider, EventBus, @@ -52,6 +53,7 @@ import type { } from "../lib/interfaces/data"; import type { ITransactionService } from "../lib/interfaces/business"; import type { + ICircleProvider, IConfigProvider, IEventBus, IOWSProvider, @@ -74,8 +76,10 @@ import { useWalletAuth } from "./useWalletAuth"; import { useWalletAssets } from "./useWalletAssets"; import { useWalletBoot } from "./useWalletBoot"; import { useWalletSessionStore } from "./sessionStore"; +import { CircleContextProvider } from "../circle/CircleContext"; /** Filled once the Signing Layer iframe finishes loading / wallet handshake. */ const configProvider: IConfigProvider = new ConfigProvider(); +const circleProvider: ICircleProvider = new CircleProvider(configProvider); const owsProvider: IOWSProvider = new OWSProvider(); const chainRepository: IChainRepository = new HardcodedChainRepository(); const blockchainProvider: IBlockchainProvider = @@ -546,6 +550,8 @@ export function WalletProvider({ children }: { children: ReactNode }) { ); return ( - {children} + + {children} + ); } diff --git a/src/wallet/modalTypes.ts b/src/wallet/modalTypes.ts index 84fa8f4..6b71d8e 100644 --- a/src/wallet/modalTypes.ts +++ b/src/wallet/modalTypes.ts @@ -12,6 +12,7 @@ import type { EVMTransactionHash, } from "@1shotapi/ows-types"; import type { IAddAssetApprovalRequest } from "./registerAddAsset"; +import type { IOnrampOpenRequest } from "../circle/onrampTypes"; export type WalletSetupChoice = "login" | "create" | "import" | "cancel"; @@ -132,6 +133,13 @@ export type ModalRequest = createUrl: string; /** true when user confirms open; false when cancelled. */ resolve: (opened: boolean) => void; + } + | { + id: string; + kind: "onramp"; + request: IOnrampOpenRequest; + resolve: () => void; + reject: (error: unknown) => void; }; export type ActiveModal = ModalRequest; diff --git a/src/wallet/registerOnramp.ts b/src/wallet/registerOnramp.ts new file mode 100644 index 0000000..2b4fbb9 --- /dev/null +++ b/src/wallet/registerOnramp.ts @@ -0,0 +1,66 @@ +import { z } from "zod"; +import type { OWSWallet } from "@1shotapi/ows-wallet-utils"; +import { + OwsUserRejectedError, + type EVMAccountAddress, +} from "@1shotapi/ows-types"; +import { openOnramp } from "../circle/openOnramp"; + +/** Custom RPC — host: `await proxy.rpc("onramp", { chainId?, amount? })`. */ +export const ONRAMP_RPC_METHOD = "onramp"; + +const onrampParamsSchema = z + .strictObject({ + chainId: z.number().int().positive().optional(), + amount: z.string().min(1).optional(), + }) + .default({}); + +export type IOnrampParams = z.infer; + +export type RegisterOnrampOptions = { + getOwnerAddress: () => EVMAccountAddress | null; +}; + +/** + * Register host `onramp` RPC — opens Circle onramp fullscreen for the + * unlocked EVM address. + */ +export function registerOnrampRpc( + wallet: OWSWallet, + options: RegisterOnrampOptions, +): void { + wallet.registerRpc( + ONRAMP_RPC_METHOD, + async (params) => { + const { chainId, amount } = params as IOnrampParams; + const owner = options.getOwnerAddress(); + if (!owner) { + throw new Error("Wallet is locked — unlock before onramp"); + } + + const display = await wallet.requestDisplay(); + try { + await openOnramp({ + destinationAddress: owner, + chainId, + amount, + }); + return { ok: true as const }; + } catch (error: unknown) { + if ( + error instanceof OwsUserRejectedError || + (error instanceof Error && /reject/i.test(error.message)) + ) { + throw error instanceof OwsUserRejectedError + ? error + : new OwsUserRejectedError("User closed onramp"); + } + throw error; + } finally { + await display.hide(); + } + }, + onrampParamsSchema, + ); +} diff --git a/src/wallet/useWalletBoot.ts b/src/wallet/useWalletBoot.ts index bf684e1..aa1df72 100644 --- a/src/wallet/useWalletBoot.ts +++ b/src/wallet/useWalletBoot.ts @@ -45,6 +45,7 @@ import { registerAddAssetRpc } from "./registerAddAsset"; import { registerCreateAccountRpc } from "./registerCreateAccount"; import type { IPasskeyRegistrationResult } from "./registerCreateAccount"; import { registerFocusModeRpc } from "./registerFocusMode"; +import { registerOnrampRpc } from "./registerOnramp"; import { loadCredentialId } from "../storage"; import { pushModal } from "./pushModal"; import type { ActiveModal, IRelayerConfirmSendResult } from "./modalTypes"; @@ -235,6 +236,16 @@ export function useWalletBoot({ registerFocusModeRpc(wallet, rpcHelper); + registerOnrampRpc(wallet, { + getOwnerAddress: () => { + const address = useWalletSessionStore.getState().evmAddress; + if (!address || String(address).toLowerCase() === "0x0") { + return null; + } + return address; + }, + }); + registerAddAssetRpc(wallet, { knownAssetRepository, trackedAssetRepository,