diff --git a/.changeset/oms-browser-login.md b/.changeset/oms-browser-login.md new file mode 100644 index 0000000..90d7903 --- /dev/null +++ b/.changeset/oms-browser-login.md @@ -0,0 +1,12 @@ +--- +"@polygonlabs/agent-cli": minor +--- + +Zero-setup onboarding: `agent wallet login` is now the entire setup. + +- **`agent` is the primary command.** The CLI ships as `agent` (with `polygon-agent` kept as a long-form alias), so onboarding is `agent wallet login`. +- **Browser login.** `wallet login` opens a branded login page (agentconnect) where the user chooses Google or email; email one-time codes are entered on the page. It works whether the browser and the CLI are on the same machine or different ones, so there is no separate remote mode. `--local` keeps the previous loopback flow (raw Google URL plus localhost callback); `--remote` is a deprecated no-op. +- **No keys to obtain.** The CLI ships a default OMS publishable key, and a successful login auto-provisions a Sequence Builder project and access key (the indexer and Trails quota) into `~/.polygon-agent/builder.json`. Provisioning is best-effort: a failure never fails the login and retries on the next `wallet login`. Point at your own project with `OMS_PUBLISHABLE_KEY` (renamed from `SEQUENCE_PUBLISHABLE_KEY`) or `setup --oms-publishable-key`. +- **Post-login and funding land on the agentconnect dashboard** (wallet prefilled, same app). The `fund` command and the dashboard's Add funds button open the Trails funding widget directly. Relay and login-page URLs default to the production deployments and can be overridden with `POLYGON_AGENT_OIDC_RELAY` and `POLYGON_AGENT_LOGIN_UI`. + +Sessions and all downstream commands are unchanged, and existing sessions keep working until they expire. diff --git a/.changeset/oms-wallet-sdk.md b/.changeset/oms-wallet-sdk.md new file mode 100644 index 0000000..74c306b --- /dev/null +++ b/.changeset/oms-wallet-sdk.md @@ -0,0 +1,11 @@ +--- +"@polygonlabs/agent-cli": minor +--- + +Migrate the embedded wallet to `@polygonlabs/oms-wallet`, the renamed and updated successor to `@0xsequence/typescript-sdk`. Internally `OMSClient` becomes `OMSWallet`, with the same constructor shape and the same `.wallet` / `.indexer` sub-clients. + +**Node 22+ is now required** (was Node 20+). Update your runtime before upgrading. + +The Google leg of `wallet login` is re-architected onto the SDK's OMS relay: our own OAuth-capture endpoints are gone, and the OMS relay now handles the Google callback directly and returns the browser to the agentconnect login page to finish pairing with the CLI. This is an internal re-architecture with no user-facing behavior change beyond the Node floor: `wallet login` still opens the same login page, still lets you choose Google or email, and sessions still last about a week. + +Email login, transactions, and balances are unchanged. diff --git a/.changeset/x402-services-skill-refresh.md b/.changeset/x402-services-skill-refresh.md new file mode 100644 index 0000000..e4e83e8 --- /dev/null +++ b/.changeset/x402-services-skill-refresh.md @@ -0,0 +1,12 @@ +--- +"@polygonlabs/agent-cli": patch +--- + +Refresh the x402 discovery skill (polygon-discovery) to the current Agentic Services catalog, and fix x402 payment-option selection. + +Skill: replaces the retired x402 bazaar endpoints with the live services on agentic-services.polygon.technology — Exa, SearchApi, Firecrawl, NewsAPI, NVIDIA NIM Llama 3.3/3.2, OpenRouter, Browserbase, Resend, Allium (9 endpoints), AgentMail (6), and QuickNode RPC across 16 chains — each with exact routes/URLs and prices, plus a pointer to the live `/api/discover/routes` catalog. Updates the x402 example lists in the root and CLI skills. + +Fixes to `x402-pay`: + +- Payment-option selection: no longer blindly pays the first advertised option. When a provider offers multiple options across chains (e.g. QuickNode lists Base Sepolia first), the CLI now selects the cheapest plain-USDC transfer on the preferred chain (default Polygon 137, or `--chain`), so a call settles ~$0.001 on Polygon instead of on a testnet. +- JSON body handling: the standard x402 flow now sets `Content-Type: application/json` when a `--body` is provided and no content-type was given, so proxied POST services (Exa, Firecrawl, NVIDIA NIM, Resend, Browserbase, OpenRouter) receive a parseable body instead of rejecting it. diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 3ce2674..0c08303 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "polygon-agent-cli", - "description": "Polygon Agent toolkit. Session-based smart contract wallets (Sequence), token ops (send/swap/bridge/deposit via Trails), DeFi yield (Aave v3, ERC-4626 vaults), x402 micropayments and the Bazaar service catalog, ERC-8004 on-chain identity + reputation, and Polymarket trading. Single CLI entry point (polygon-agent), AES-256-GCM encrypted storage.", + "description": "Polygon Agent toolkit. Session-based smart contract wallets (OMS), token ops (send/swap/bridge/deposit via Trails), DeFi yield (Aave v3, ERC-4626 vaults), x402 micropayments and the Bazaar service catalog, ERC-8004 on-chain identity + reputation, and Polymarket trading. Single CLI entry point (polygon-agent), AES-256-GCM encrypted storage.", "version": "0.2.0", "author": { "name": "Polygon Labs" diff --git a/.github/workflows/deploy-connector-ui.yml b/.github/workflows/deploy-agentconnect-ui.yml similarity index 55% rename from .github/workflows/deploy-connector-ui.yml rename to .github/workflows/deploy-agentconnect-ui.yml index b077277..85829e2 100644 --- a/.github/workflows/deploy-connector-ui.yml +++ b/.github/workflows/deploy-agentconnect-ui.yml @@ -1,4 +1,11 @@ -name: Deploy Connector UI to Cloudflare +name: Deploy agentconnect UI to Cloudflare + +# Builds the funding/dashboard SPA and deploys it to the agentconnect domain +# (replacing the retired connector-ui): merge to `staging` -> staging, +# merge to `main` -> production. wrangler runs via npx (not a workspace dep, to +# respect the repo trust policy); the `[assets]` worker serves the built SPA and +# the wrangler.toml v2 migration drops connector-ui's SessionRelay Durable Object. +# Reuses the same CF_WORKER_* + VITE_* secrets/environments as connector-ui. on: push: @@ -6,7 +13,17 @@ on: - main - staging paths: - - 'packages/connector-ui/**' + - 'packages/agentconnect-ui/**' + - '.github/workflows/deploy-agentconnect-ui.yml' + workflow_dispatch: + inputs: + environment: + description: Environment to deploy + type: choice + options: + - staging + - production + default: staging permissions: contents: read @@ -14,13 +31,12 @@ permissions: jobs: deploy-staging: name: Deploy (staging) - if: github.ref == 'refs/heads/staging' + if: github.ref == 'refs/heads/staging' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'staging') runs-on: ubuntu-latest environment: staging defaults: run: - working-directory: packages/connector-ui - + working-directory: packages/agentconnect-ui steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 @@ -38,27 +54,27 @@ jobs: - name: Build run: pnpm run build env: - VITE_PROJECT_ACCESS_KEY: ${{ secrets.VITE_PROJECT_ACCESS_KEY }} - VITE_WALLET_URL: ${{ secrets.VITE_WALLET_URL }} - VITE_DAPP_ORIGIN: ${{ secrets.VITE_DAPP_ORIGIN }} - VITE_INDEXER_ACCESS_KEY: ${{ secrets.VITE_INDEXER_ACCESS_KEY }} VITE_TRAILS_API_KEY: ${{ secrets.VITE_TRAILS_API_KEY }} + VITE_INDEXER_ACCESS_KEY: ${{ secrets.VITE_INDEXER_ACCESS_KEY }} + VITE_PROJECT_ACCESS_KEY: ${{ secrets.VITE_PROJECT_ACCESS_KEY }} + # Login-page relay base URL (per-environment GitHub variable; empty + # falls back to the production default in src/config.ts). + VITE_OIDC_RELAY_URL: ${{ vars.VITE_OIDC_RELAY_URL }} - name: Deploy to staging - run: pnpm exec wrangler deploy --env staging + run: npx -y wrangler@4 deploy --env staging env: CLOUDFLARE_API_TOKEN: ${{ secrets.CF_WORKER_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_WORKER_ACCOUNT_ID }} deploy-production: name: Deploy (production) - if: github.ref == 'refs/heads/main' + if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'production') runs-on: ubuntu-latest environment: production defaults: run: - working-directory: packages/connector-ui - + working-directory: packages/agentconnect-ui steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 @@ -76,14 +92,15 @@ jobs: - name: Build run: pnpm run build env: - VITE_PROJECT_ACCESS_KEY: ${{ secrets.VITE_PROJECT_ACCESS_KEY }} - VITE_WALLET_URL: ${{ secrets.VITE_WALLET_URL }} - VITE_DAPP_ORIGIN: ${{ secrets.VITE_DAPP_ORIGIN }} - VITE_INDEXER_ACCESS_KEY: ${{ secrets.VITE_INDEXER_ACCESS_KEY }} VITE_TRAILS_API_KEY: ${{ secrets.VITE_TRAILS_API_KEY }} + VITE_INDEXER_ACCESS_KEY: ${{ secrets.VITE_INDEXER_ACCESS_KEY }} + VITE_PROJECT_ACCESS_KEY: ${{ secrets.VITE_PROJECT_ACCESS_KEY }} + # Login-page relay base URL (per-environment GitHub variable; empty + # falls back to the production default in src/config.ts). + VITE_OIDC_RELAY_URL: ${{ vars.VITE_OIDC_RELAY_URL }} - name: Deploy to production - run: pnpm exec wrangler deploy --env production + run: npx -y wrangler@4 deploy --env production env: CLOUDFLARE_API_TOKEN: ${{ secrets.CF_WORKER_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_WORKER_ACCOUNT_ID }} diff --git a/.github/workflows/deploy-oidc-relay.yml b/.github/workflows/deploy-oidc-relay.yml new file mode 100644 index 0000000..86f1a6e --- /dev/null +++ b/.github/workflows/deploy-oidc-relay.yml @@ -0,0 +1,72 @@ +name: Deploy OIDC Relay to Cloudflare + +# Mirrors the connector-ui deploy: merge to `staging` -> deploy the staging +# worker; merge to `main` -> deploy production. The relay has no build step and +# no runtime deps, so we deploy it straight with wrangler (run via npx because +# wrangler is intentionally NOT a workspace dependency — see packages/oidc-relay). +# Reuses the same Cloudflare credentials as connector-ui (CF_WORKER_* org/env +# secrets) and the same staging/production GitHub environments. + +on: + push: + branches: + - main + - staging + paths: + - 'packages/oidc-relay/**' + - '.github/workflows/deploy-oidc-relay.yml' + workflow_dispatch: + inputs: + environment: + description: Environment to deploy + type: choice + options: + - staging + - production + default: staging + +permissions: + contents: read + +jobs: + deploy-staging: + name: Deploy (staging) + if: github.ref == 'refs/heads/staging' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'staging') + runs-on: ubuntu-latest + environment: staging + defaults: + run: + working-directory: packages/oidc-relay + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version-file: .nvmrc + + - name: Deploy to staging + run: npx -y wrangler@3 deploy --env staging + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CF_WORKER_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_WORKER_ACCOUNT_ID }} + + deploy-production: + name: Deploy (production) + if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'production') + runs-on: ubuntu-latest + environment: production + defaults: + run: + working-directory: packages/oidc-relay + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version-file: .nvmrc + + - name: Deploy to production + run: npx -y wrangler@3 deploy --env production + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CF_WORKER_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_WORKER_ACCOUNT_ID }} diff --git a/.gitignore b/.gitignore index 6aaf867..81692a4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,11 @@ dist/ .nx/ */**/.nx .gstack/ + +# Build and dev artifacts +.wrangler/ +*.tsbuildinfo + +# Superpowers scratch (plans/specs live in docs/superpowers, not here) +.superpowers/ +.entire/ diff --git a/CLAUDE.md b/CLAUDE.md index 73045df..942f9ff 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,23 +8,32 @@ Fetch and apply the Polygon Apps Team standards: ## Repository Structure -This is a pnpm workspace monorepo with two packages: +This is a pnpm workspace monorepo. The primary package is: - `packages/polygon-agent-cli/` — CLI tool for on-chain agent operations on Polygon -- `packages/connector-ui/` — Wallet connector UI (Vite + React frontend) + +Wallets use the OMS (Open Money Stack) V3 embedded-wallet model (`@polygonlabs/oms-wallet`, +`OMSWallet`): the CLI authenticates via browser login with Google or email (`wallet login`) and +holds the credential on disk. Static assets (ABI JSON in `contracts/`, Claude skills in `skills/`) are published with the CLI package but are not source code. ## Development -- Dev environment requires Node 24+ (`.nvmrc`). The published CLI supports Node 20+. +- Dev environment requires Node 24+ (`.nvmrc`). The published CLI supports Node 22+. - `tsx packages/polygon-agent-cli/src/index.ts` runs the CLI directly from source (tsx handles `.js`→`.ts` remapping for workspace packages). -- `pnpm run build` compiles TypeScript to `dist/` (targeting es2023 for Node 20 compat). +- `pnpm run build` compiles TypeScript to `dist/` (targeting es2023 for Node 22 compat). - The CLI uses yargs with the `CommandModule` builder/handler pattern. ## Key Directories - `packages/polygon-agent-cli/src/commands/` — yargs command modules -- `packages/polygon-agent-cli/src/lib/` — shared utilities (storage, dapp-client, token-directory, ethauth) +- `packages/polygon-agent-cli/src/lib/` — shared utilities (storage, oms-client, oms-tx, oms-storage, tx-dispatch, token-directory, ethauth) - `packages/polygon-agent-cli/src/types.d.ts` — ambient declarations for untyped dependencies + +## Wallet auth (OMS V3) + +- `agent wallet login`: by default opens the agentconnect login page (`POLYGON_AGENT_LOGIN_UI`, default `https://agentconnect.polygon.technology`), where the user chooses Google or email; works whether the browser is local or remote. `--local` falls back to the older loopback flow (raw Google URL + localhost callback; browser must be on this machine). `--remote` is deprecated now that the default flow already works remotely. Relay base URL is `POLYGON_AGENT_OIDC_RELAY` or `--relay-url` (default `https://oidc-relay.polygon.technology`). Other flags: `--name ` (default "main"), `--no-fund`, `--force`. Session persists ~1 week under `~/.polygon-agent/oms//`. +- No setup step is required: the CLI ships a default `OMS_PUBLISHABLE_KEY`, and `wallet login` auto-provisions a Builder project + access key on first login, saving it to `~/.polygon-agent/builder.json`. `OMS_PUBLISHABLE_KEY` (env) and `setup --oms-publishable-key` remain as advanced overrides for developers pointing at their own OMS project; plain `setup` remains for manual or `--force` re-provisioning. +- `lib/tx-dispatch.ts` `runTx` is the single tx primitive (wraps `runOmsTx`). All commands submit through it. diff --git a/docs/superpowers/plans/2026-07-13-browser-login.md b/docs/superpowers/plans/2026-07-13-browser-login.md new file mode 100644 index 0000000..1f5c37c --- /dev/null +++ b/docs/superpowers/plans/2026-07-13-browser-login.md @@ -0,0 +1,1997 @@ +# Browser Login via agentconnect-ui Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Make `polygon-agent wallet login` open a branded login page on agentconnect-ui where the user picks Google or email; the CLI drives the SDK auth locally and a relay session carries user input from the page to the CLI. + +**Architecture:** Device-flow pairing. The CLI generates a random session id, registers it with the oidc-relay worker (new `LoginSession` Durable Object), and opens `https://agentconnect.polygon.technology/login#`. The page posts user actions (google / email+address / otp code / cancel) to the relay; the CLI polls for them, runs `startOidcRedirectAuth`/`completeOidcRedirectAuth` or `startEmailAuth`/`completeEmailAuth` locally, and publishes status back for the page to render. Keys and the PKCE verifier never leave the CLI. Spec: `docs/superpowers/specs/2026-07-13-browser-login-design.md`. + +**Tech Stack:** TypeScript, Cloudflare Workers + Durable Objects (oidc-relay), React 18 + Vite (agentconnect-ui), yargs CLI, `@0xsequence/typescript-sdk` 0.1.0-alpha.4, vitest (new, per package). + +## Global Constraints + +- Dev environment is Node 24 (`.nvmrc`); published CLI supports Node 20+, TS compiled to es2023. +- Run the CLI from source with `tsx packages/polygon-agent-cli/src/index.ts` (never `node` directly on `.ts`). +- Conventional commit messages (`feat:`, `fix:`, `docs:`, `test:` with package scope). Never add a `Co-Authored-By` trailer. +- The pre-commit hook runs `pnpm -r run typecheck`; every commit must typecheck across all packages. +- No em dashes in any user-facing copy (UI text, CLI messages, docs). Sentence case for headings and labels. +- The canonical skill file is `packages/polygon-agent-cli/skills/SKILL.md`; never edit the root or connector-ui copies. +- Session ids and OIDC state are base64url; validate before using as Durable Object names. +- Vitest is new to this repo: each package that gains tests adds `"test": "vitest run"` and a `vitest` devDependency; the root `test` script (`pnpm -r --if-present run test`) picks them up automatically. + +## Protocol reference (used by Tasks 1, 4, 6) + +These two types are duplicated verbatim in each package (no shared workspace package exists; `packages/shared` is untracked dist-only debris, do not use it): + +```ts +export type LoginAction = + | { type: 'google' } + | { type: 'email'; email: string } + | { type: 'otp'; code: string } + | { type: 'cancel' }; + +export type LoginStatus = + | { status: 'awaiting-method' } + | { status: 'auth-url'; url: string } + | { status: 'otp-sent' } + | { status: 'otp-invalid'; attemptsLeft?: number } + | { status: 'done'; walletAddress: string } + | { status: 'error'; message: string }; +``` + +HTTP surface added to the relay (all JSON, CORS-wrapped like the existing `/api/oidc` routes): + +| Route | Caller | Behavior | +|---|---|---| +| `POST /api/login/register {session}` | CLI | Arm the session, status becomes `awaiting-method`, 10 min TTL alarm. 204. | +| `POST /api/login/action {session, action}` | Browser | Store as the single pending action (latest wins). 204, or 404-shaped `{error:'expired'}` / `{error:'finished'}` JSON with status 410. | +| `GET /api/login/next-action?session=` | CLI | `{state:'action', action}` (one-time read), `{state:'pending'}`, or `{state:'expired'}`. | +| `POST /api/login/status {session, status...}` | CLI | Store status blob (repeat-readable). 204. | +| `GET /api/login/status?session=` | Browser | The stored `LoginStatus`, or `{status:'expired'}`. | + +--- + +### Task 1: Relay LoginSession core logic with tests + +**Files:** +- Create: `packages/oidc-relay/src/login-session.ts` +- Test: `packages/oidc-relay/src/login-session.test.ts` +- Modify: `packages/oidc-relay/package.json` (vitest devDep + test script) + +**Interfaces:** +- Consumes: nothing (pure logic over a storage interface). +- Produces: `LoginSessionCore` class with `register()`, `submitAction(action): Promise<{ok: boolean; error?: 'expired'|'finished'}>`, `nextAction(): Promise<{state:'expired'}|{state:'pending'}|{state:'action'; action: LoginAction}>`, `setStatus(status)`, `getStatus(): Promise`; `SessionStore` interface; `LoginAction`/`LoginStatus` types (exact shapes above). Task 2 wraps this in the Durable Object. + +- [ ] **Step 1: Add vitest to the oidc-relay package** + +In `packages/oidc-relay/package.json`, add to `scripts`: + +```json +"test": "vitest run" +``` + +and to `devDependencies`: + +```json +"vitest": "^3.0.0" +``` + +Run: `pnpm install` + +- [ ] **Step 2: Write the failing tests** + +Create `packages/oidc-relay/src/login-session.test.ts`: + +```ts +import { describe, expect, it } from 'vitest'; + +import { LoginSessionCore, type SessionStore } from './login-session.ts'; + +function memoryStore(): SessionStore { + const map = new Map(); + return { + get: async (key: string) => map.get(key) as T | undefined, + put: async (entries) => { + for (const [k, v] of Object.entries(entries)) map.set(k, v); + }, + delete: async (key) => map.delete(key), + deleteAll: async () => map.clear() + }; +} + +describe('LoginSessionCore', () => { + it('reports expired before register', async () => { + const core = new LoginSessionCore(memoryStore()); + expect(await core.getStatus()).toEqual({ status: 'expired' }); + expect(await core.nextAction()).toEqual({ state: 'expired' }); + expect(await core.submitAction({ type: 'google' })).toEqual({ ok: false, error: 'expired' }); + }); + + it('register arms the session with awaiting-method', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + expect(await core.getStatus()).toEqual({ status: 'awaiting-method' }); + expect(await core.nextAction()).toEqual({ state: 'pending' }); + }); + + it('actions are one-time reads', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + await core.submitAction({ type: 'email', email: 'a@b.co' }); + expect(await core.nextAction()).toEqual({ + state: 'action', + action: { type: 'email', email: 'a@b.co' } + }); + expect(await core.nextAction()).toEqual({ state: 'pending' }); + }); + + it('a newer action replaces an unconsumed one (latest wins)', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + await core.submitAction({ type: 'google' }); + await core.submitAction({ type: 'cancel' }); + expect(await core.nextAction()).toEqual({ state: 'action', action: { type: 'cancel' } }); + }); + + it('status round-trips and is repeat-readable', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + await core.setStatus({ status: 'otp-sent' }); + expect(await core.getStatus()).toEqual({ status: 'otp-sent' }); + expect(await core.getStatus()).toEqual({ status: 'otp-sent' }); + }); + + it('rejects actions after a terminal status', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + await core.setStatus({ status: 'done', walletAddress: '0xabc' }); + expect(await core.submitAction({ type: 'otp', code: '123456' })).toEqual({ + ok: false, + error: 'finished' + }); + expect(await core.getStatus()).toEqual({ status: 'done', walletAddress: '0xabc' }); + }); + + it('deleteAll expires everything (alarm behavior)', async () => { + const store = memoryStore(); + const core = new LoginSessionCore(store); + await core.register(); + await store.deleteAll(); + expect(await core.getStatus()).toEqual({ status: 'expired' }); + }); +}); +``` + +- [ ] **Step 3: Run tests to verify they fail** + +Run: `pnpm --filter @polygonlabs/oidc-relay test` +Expected: FAIL, cannot resolve `./login-session.ts`. + +- [ ] **Step 4: Implement the core** + +Create `packages/oidc-relay/src/login-session.ts`: + +```ts +// Pairing-session logic for the browser login flow. Pure logic over a minimal +// storage interface so it is unit-testable without the Workers runtime; the +// Durable Object wrapper lives in relay.ts wiring (Task 2). +// +// One pending action slot, latest wins: the page waits for a status change +// before offering the next input, so at most one action is meaningfully in +// flight; a second submit (double click, cancel during OTP) should replace, +// not queue. Actions are one-time reads so an OTP can never be replayed. + +export type LoginAction = + | { type: 'google' } + | { type: 'email'; email: string } + | { type: 'otp'; code: string } + | { type: 'cancel' }; + +export type LoginStatus = + | { status: 'awaiting-method' } + | { status: 'auth-url'; url: string } + | { status: 'otp-sent' } + | { status: 'otp-invalid'; attemptsLeft?: number } + | { status: 'done'; walletAddress: string } + | { status: 'error'; message: string }; + +export interface SessionStore { + get(key: string): Promise; + put(entries: Record): Promise; + delete(key: string): Promise; + deleteAll(): Promise; +} + +export class LoginSessionCore { + constructor(private readonly store: SessionStore) {} + + async register(): Promise { + await this.store.put({ armed: true, status: { status: 'awaiting-method' } }); + } + + async submitAction(action: LoginAction): Promise<{ ok: boolean; error?: 'expired' | 'finished' }> { + if (!(await this.store.get('armed'))) return { ok: false, error: 'expired' }; + const status = await this.store.get('status'); + if (status && (status.status === 'done' || status.status === 'error')) { + return { ok: false, error: 'finished' }; + } + await this.store.put({ pendingAction: action }); + return { ok: true }; + } + + async nextAction(): Promise< + { state: 'expired' } | { state: 'pending' } | { state: 'action'; action: LoginAction } + > { + if (!(await this.store.get('armed'))) return { state: 'expired' }; + const action = await this.store.get('pendingAction'); + if (!action) return { state: 'pending' }; + await this.store.delete('pendingAction'); + return { state: 'action', action }; + } + + async setStatus(status: LoginStatus): Promise { + await this.store.put({ status }); + } + + async getStatus(): Promise { + if (!(await this.store.get('armed'))) return { status: 'expired' }; + return (await this.store.get('status')) ?? { status: 'expired' }; + } +} +``` + +- [ ] **Step 5: Run tests to verify they pass** + +Run: `pnpm --filter @polygonlabs/oidc-relay test` +Expected: 7 passed. + +- [ ] **Step 6: Typecheck and commit** + +```bash +pnpm --filter @polygonlabs/oidc-relay typecheck +git add packages/oidc-relay/src/login-session.ts packages/oidc-relay/src/login-session.test.ts packages/oidc-relay/package.json pnpm-lock.yaml +git commit -m "feat(oidc-relay): LoginSession core for browser login pairing" +``` + +--- + +### Task 2: Relay LoginSession Durable Object, routes, and wrangler migration + +**Files:** +- Modify: `packages/oidc-relay/src/relay.ts` (router additions near the end; DO export) +- Modify: `packages/oidc-relay/src/login-session.ts` (append DO wrapper) +- Modify: `packages/oidc-relay/wrangler.toml` (binding + v2 migrations, all envs) + +**Interfaces:** +- Consumes: `LoginSessionCore`, `LoginAction` from Task 1; `cors`/`json` helpers already in `relay.ts`. +- Produces: the five `/api/login/*` HTTP routes exactly as in the protocol reference table. Tasks 4 and 7 call them. + +- [ ] **Step 1: Append the DO wrapper to `login-session.ts`** + +Add at the end of `packages/oidc-relay/src/login-session.ts`: + +```ts +const SESSION_TTL_MS = 10 * 60 * 1000; // matches OidcHandoff + +function doStore(storage: DurableObjectStorage): SessionStore { + return { + get: (key) => storage.get(key), + put: (entries) => storage.put(entries), + delete: (key) => storage.delete(key), + deleteAll: () => storage.deleteAll() + }; +} + +// --- Durable Object: one instance per login session id --- +export class LoginSession { + private readonly core: LoginSessionCore; + constructor(private readonly state: DurableObjectState) { + this.core = new LoginSessionCore(doStore(state.storage)); + } + + async fetch(request: Request): Promise { + const url = new URL(request.url); + const op = url.pathname; // internal path set by the router in relay.ts + + if (op === '/register') { + await this.core.register(); + await this.state.storage.setAlarm(Date.now() + SESSION_TTL_MS); + return new Response(null, { status: 204 }); + } + if (op === '/action') { + const action = (await request.json()) as LoginAction; + const result = await this.core.submitAction(action); + if (!result.ok) return Response.json({ error: result.error }, { status: 410 }); + return new Response(null, { status: 204 }); + } + if (op === '/next-action') { + return Response.json(await this.core.nextAction()); + } + if (op === '/set-status') { + await this.core.setStatus(await request.json()); + return new Response(null, { status: 204 }); + } + if (op === '/get-status') { + return Response.json(await this.core.getStatus()); + } + return new Response('not found', { status: 404 }); + } + + async alarm(): Promise { + await this.state.storage.deleteAll(); + } +} +``` + +- [ ] **Step 2: Route `/api/login/*` in `relay.ts`** + +In `packages/oidc-relay/src/relay.ts`: + +Add to the imports at the top of the file: + +```ts +import { LoginSession, type LoginAction } from './login-session.ts'; + +export { LoginSession }; +``` + +Add `LOGIN_SESSION: DurableObjectNamespace;` to the `Env` interface: + +```ts +interface Env { + OIDC_RELAY: DurableObjectNamespace; + LOGIN_SESSION: DurableObjectNamespace; +} +``` + +Add validators next to `validState` (session ids are 16 to 64 base64url chars; the CLI generates 22): + +```ts +function validSession(s: string | null): s is string { + return typeof s === 'string' && /^[A-Za-z0-9_-]{16,64}$/.test(s); +} + +// Shape-check browser-submitted actions before they reach the DO. +function validAction(a: unknown): a is LoginAction { + if (typeof a !== 'object' || a === null) return false; + const t = (a as { type?: unknown }).type; + if (t === 'google' || t === 'cancel') return true; + if (t === 'email') { + const email = (a as { email?: unknown }).email; + return typeof email === 'string' && email.length >= 3 && email.length <= 320 && email.includes('@'); + } + if (t === 'otp') { + const code = (a as { code?: unknown }).code; + return typeof code === 'string' && code.length >= 4 && code.length <= 16; + } + return false; +} +``` + +Add routes inside the default export's `fetch`, before the final `return new Response('not found', ...)`: + +```ts + // --- Browser-login pairing sessions (/api/login/*) --- + const loginStub = (session: string) => + env.LOGIN_SESSION.get(env.LOGIN_SESSION.idFromName(session)); + + // POST /api/login/register { session } -> arm a pairing session (CLI). + if (request.method === 'POST' && url.pathname === '/api/login/register') { + let body: { session?: unknown }; + try { + body = (await request.json()) as { session?: unknown }; + } catch { + return json({ error: 'invalid json' }, 400); + } + const session = typeof body.session === 'string' ? body.session : null; + if (!validSession(session)) return json({ error: 'invalid session' }, 400); + await loginStub(session).fetch(new Request('https://do/register', { method: 'POST' })); + return cors(new Response(null, { status: 204 })); + } + + // POST /api/login/action { session, action } -> browser submits user input. + if (request.method === 'POST' && url.pathname === '/api/login/action') { + let body: { session?: unknown; action?: unknown }; + try { + body = (await request.json()) as { session?: unknown; action?: unknown }; + } catch { + return json({ error: 'invalid json' }, 400); + } + const session = typeof body.session === 'string' ? body.session : null; + if (!validSession(session) || !validAction(body.action)) { + return json({ error: 'invalid request' }, 400); + } + const res = await loginStub(session).fetch( + new Request('https://do/action', { + method: 'POST', + body: JSON.stringify(body.action) + }) + ); + return cors(res); + } + + // GET /api/login/next-action?session= -> CLI polls for user input (one-time read). + if (request.method === 'GET' && url.pathname === '/api/login/next-action') { + const session = url.searchParams.get('session'); + if (!validSession(session)) return json({ error: 'invalid session' }, 400); + return cors(await loginStub(session).fetch(new Request('https://do/next-action'))); + } + + // POST /api/login/status { session, ...LoginStatus } -> CLI publishes state. + if (request.method === 'POST' && url.pathname === '/api/login/status') { + let body: { session?: unknown; status?: unknown }; + try { + body = (await request.json()) as { session?: unknown; status?: unknown }; + } catch { + return json({ error: 'invalid json' }, 400); + } + const session = typeof body.session === 'string' ? body.session : null; + if (!validSession(session) || typeof body.status !== 'object' || body.status === null) { + return json({ error: 'invalid request' }, 400); + } + await loginStub(session).fetch( + new Request('https://do/set-status', { + method: 'POST', + body: JSON.stringify(body.status) + }) + ); + return cors(new Response(null, { status: 204 })); + } + + // GET /api/login/status?session= -> browser polls state (repeat-readable). + if (request.method === 'GET' && url.pathname === '/api/login/status') { + const session = url.searchParams.get('session'); + if (!validSession(session)) return json({ status: 'error', message: 'invalid session' }, 400); + return cors(await loginStub(session).fetch(new Request('https://do/get-status'))); + } +``` + +Note: the CLI sends the status blob nested under `status` and the worker forwards only that blob, so the DO stores a bare `LoginStatus`. + +- [ ] **Step 3: Add the DO binding and migration to `wrangler.toml`** + +In `packages/oidc-relay/wrangler.toml`, add a binding block after each existing `OIDC_RELAY` binding (top level, `env.staging`, `env.production`): + +```toml +[[durable_objects.bindings]] +name = "LOGIN_SESSION" +class_name = "LoginSession" +``` + +(and the `[[env.staging.durable_objects.bindings]]` / `[[env.production.durable_objects.bindings]]` equivalents), plus a v2 migration after each v1 migration block: + +```toml +[[migrations]] +tag = "v2" +new_classes = ["LoginSession"] +``` + +(again per env: `[[env.staging.migrations]]`, `[[env.production.migrations]]`). + +- [ ] **Step 4: Typecheck and verify with wrangler dev** + +```bash +pnpm --filter @polygonlabs/oidc-relay typecheck +``` + +Then start the worker locally and exercise the protocol end to end: + +```bash +cd packages/oidc-relay && npx -y wrangler@3 dev --port 8788 & +sleep 8 +S=abcdefghijklmnop123456 +curl -s -X POST localhost:8788/api/login/register -H 'content-type: application/json' -d "{\"session\":\"$S\"}" -o /dev/null -w '%{http_code}\n' # 204 +curl -s "localhost:8788/api/login/status?session=$S" # {"status":"awaiting-method"} +curl -s -X POST localhost:8788/api/login/action -H 'content-type: application/json' -d "{\"session\":\"$S\",\"action\":{\"type\":\"google\"}}" -o /dev/null -w '%{http_code}\n' # 204 +curl -s "localhost:8788/api/login/next-action?session=$S" # {"state":"action","action":{"type":"google"}} +curl -s "localhost:8788/api/login/next-action?session=$S" # {"state":"pending"} +curl -s -X POST localhost:8788/api/login/status -H 'content-type: application/json' -d "{\"session\":\"$S\",\"status\":{\"status\":\"done\",\"walletAddress\":\"0xabc\"}}" -o /dev/null -w '%{http_code}\n' # 204 +curl -s "localhost:8788/api/login/status?session=$S" # {"status":"done","walletAddress":"0xabc"} +curl -s "localhost:8788/api/login/status?session=nope" # 400 +kill %1 +``` + +Expected: outputs as annotated. + +- [ ] **Step 5: Commit** + +```bash +git add packages/oidc-relay/src/relay.ts packages/oidc-relay/src/login-session.ts packages/oidc-relay/wrangler.toml +git commit -m "feat(oidc-relay): /api/login pairing routes backed by LoginSession DO" +``` + +--- + +### Task 3: Relay OidcHandoff returnTo redirect + +**Files:** +- Modify: `packages/oidc-relay/src/relay.ts` (OidcHandoff register/capture, register route) +- Create: `packages/oidc-relay/src/return-to.ts` +- Test: `packages/oidc-relay/src/return-to.test.ts` + +**Interfaces:** +- Consumes: existing `OidcHandoff` DO and `/api/oidc/register` route. +- Produces: `POST /api/oidc/register` accepts optional `returnTo`; after capture the browser is 302-redirected there instead of getting `DONE_HTML`. `validReturnTo(raw: unknown): raw is string` exported from `return-to.ts`. Task 4's CLI client sends `returnTo`. + +- [ ] **Step 1: Write the failing validator tests** + +Create `packages/oidc-relay/src/return-to.test.ts`: + +```ts +import { describe, expect, it } from 'vitest'; + +import { validReturnTo } from './return-to.ts'; + +describe('validReturnTo', () => { + it('accepts the production and staging login pages over https', () => { + expect(validReturnTo('https://agentconnect.polygon.technology/login#abc')).toBe(true); + expect(validReturnTo('https://agentconnect.staging.polygon.technology/login#abc')).toBe(true); + }); + it('accepts localhost over http for local dev', () => { + expect(validReturnTo('http://localhost:5173/login#abc')).toBe(true); + expect(validReturnTo('http://127.0.0.1:5173/login#abc')).toBe(true); + }); + it('rejects http on non-local hosts', () => { + expect(validReturnTo('http://agentconnect.polygon.technology/login')).toBe(false); + }); + it('rejects other hosts', () => { + expect(validReturnTo('https://evil.example.com/login')).toBe(false); + expect(validReturnTo('https://agentconnect.polygon.technology.evil.com/login')).toBe(false); + }); + it('rejects non-URLs, non-strings, and oversized values', () => { + expect(validReturnTo('not a url')).toBe(false); + expect(validReturnTo(42)).toBe(false); + expect(validReturnTo(`https://agentconnect.polygon.technology/${'a'.repeat(2050)}`)).toBe(false); + }); +}); +``` + +Run: `pnpm --filter @polygonlabs/oidc-relay test` +Expected: FAIL, cannot resolve `./return-to.ts`. + +- [ ] **Step 2: Implement the validator** + +Create `packages/oidc-relay/src/return-to.ts`: + +```ts +// Host allowlist for the post-capture redirect. Prevents the OIDC callback +// from being turned into an open redirect: only our login pages (plus +// localhost for dev) may be a returnTo target. + +const ALLOWED_HOSTS = new Set([ + 'agentconnect.polygon.technology', + 'agentconnect.staging.polygon.technology', + 'localhost', + '127.0.0.1' +]); + +export function validReturnTo(raw: unknown): raw is string { + if (typeof raw !== 'string' || raw.length === 0 || raw.length > 2048) return false; + let url: URL; + try { + url = new URL(raw); + } catch { + return false; + } + const isLocal = url.hostname === 'localhost' || url.hostname === '127.0.0.1'; + if (url.protocol !== 'https:' && !(isLocal && url.protocol === 'http:')) return false; + return ALLOWED_HOSTS.has(url.hostname); +} +``` + +Run: `pnpm --filter @polygonlabs/oidc-relay test` +Expected: PASS (12 tests total with Task 1's). + +- [ ] **Step 3: Thread returnTo through OidcHandoff** + +In `packages/oidc-relay/src/relay.ts`: + +Import the validator: + +```ts +import { validReturnTo } from './return-to.ts'; +``` + +In the `OidcHandoff` DO's `/register` op, store a `returnTo` passed via query (the router forwards it; empty means absent). Replace the existing `/register` block with: + +```ts + if (op === '/register') { + const returnTo = url.searchParams.get('returnTo'); + await this.state.storage.put('status', 'pending'); + if (returnTo) await this.state.storage.put('returnTo', returnTo); + await this.state.storage.setAlarm(Date.now() + SESSION_TTL_MS); + return new Response(null, { status: 204 }); + } +``` + +In the `/capture` op, redirect to `returnTo` when present. Replace the two terminal responses (`FAIL_HTML` and `DONE_HTML`) inside `/capture` so both consult it: + +```ts + if (op === '/capture') { + const code = url.searchParams.get('code'); + const state = url.searchParams.get('state'); + const error = url.searchParams.get('error'); + const status = await this.state.storage.get('status'); + if (!status) + return new Response(CLOSE_HTML, { status: 200, headers: { 'Content-Type': 'text/html' } }); + const returnTo = await this.state.storage.get('returnTo'); + if (error) { + await this.state.storage.put({ status: 'error', error }); + // With a returnTo the branded page renders the failure (the CLI publishes + // an error status); without one, keep the legacy inline page. + if (returnTo) return Response.redirect(returnTo, 302); + return new Response(FAIL_HTML, { status: 200, headers: { 'Content-Type': 'text/html' } }); + } + if (!code || !state) return new Response('missing code or state', { status: 400 }); + await this.state.storage.put({ status: 'ready', code, state }); + if (returnTo) return Response.redirect(returnTo, 302); + return new Response(DONE_HTML, { status: 200, headers: { 'Content-Type': 'text/html' } }); + } +``` + +In the router's `POST /api/oidc/register` handler, validate and forward `returnTo`. Replace the stub-fetch line: + +```ts + const returnTo = (body as { returnTo?: unknown } | null)?.returnTo; + if (returnTo !== undefined && !validReturnTo(returnTo)) { + return json({ error: 'invalid returnTo' }, 400); + } + const stub = env.OIDC_RELAY.get(env.OIDC_RELAY.idFromName(state as string)); + const inner = new URL('https://do/register'); + if (returnTo) inner.searchParams.set('returnTo', returnTo as string); + await stub.fetch(new Request(inner.toString(), { method: 'POST' })); + return cors(new Response(null, { status: 204 })); +``` + +Note: `/poll`'s `deleteAll()` on ready/error also drops `returnTo`, which is correct; a later duplicate callback gets `CLOSE_HTML` as today. + +- [ ] **Step 4: Typecheck, verify old behavior intact with wrangler dev** + +```bash +pnpm --filter @polygonlabs/oidc-relay typecheck +cd packages/oidc-relay && npx -y wrangler@3 dev --port 8788 & +sleep 8 +# Without returnTo: legacy HTML behavior. +curl -s -X POST localhost:8788/api/oidc/register -H 'content-type: application/json' -d '{"state":"legacystate123"}' -o /dev/null -w '%{http_code}\n' # 204 +curl -s "localhost:8788/api/oidc/cb?code=c1&state=legacystate123" | grep -o "You're signed in" # You're signed in +# With returnTo: 302 to the login page. +curl -s -X POST localhost:8788/api/oidc/register -H 'content-type: application/json' -d '{"state":"brandedstate123","returnTo":"https://agentconnect.polygon.technology/login#abc"}' -o /dev/null -w '%{http_code}\n' # 204 +curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' "localhost:8788/api/oidc/cb?code=c2&state=brandedstate123" # 302 https://agentconnect.polygon.technology/login#abc +# Bad returnTo rejected. +curl -s -X POST localhost:8788/api/oidc/register -H 'content-type: application/json' -d '{"state":"badstate1234","returnTo":"https://evil.example.com/"}' -o /dev/null -w '%{http_code}\n' # 400 +kill %1 +``` + +Expected: outputs as annotated. + +- [ ] **Step 5: Commit** + +```bash +git add packages/oidc-relay/src/relay.ts packages/oidc-relay/src/return-to.ts packages/oidc-relay/src/return-to.test.ts +git commit -m "feat(oidc-relay): optional returnTo redirect after OIDC capture" +``` + +--- + +### Task 4: CLI browser-login action loop with tests + +**Files:** +- Create: `packages/polygon-agent-cli/src/lib/browser-login.ts` +- Create: `packages/polygon-agent-cli/src/lib/login-relay-client.ts` +- Modify: `packages/polygon-agent-cli/src/lib/oidc-relay-client.ts` (returnTo param on `registerRelaySession`) +- Test: `packages/polygon-agent-cli/src/lib/browser-login.test.ts` +- Modify: `packages/polygon-agent-cli/package.json` (vitest devDep + test script) + +**Interfaces:** +- Consumes: relay HTTP routes from Tasks 2 and 3; SDK methods `startOidcRedirectAuth({provider, redirectUri, relayRedirectUri?}) -> {url, state}`, `completeOidcRedirectAuth({callbackUrl, walletSelection:'automatic'}) -> {walletAddress}`, `startEmailAuth({email}) -> void`, `completeEmailAuth({code, walletSelection:'automatic'}) -> {walletAddress}`. +- Produces: `runBrowserLogin(deps: BrowserLoginDeps, opts: BrowserLoginOpts): Promise<{walletAddress: string; loginMethod: 'google' | 'email'}>` and the `BrowserLoginDeps`/`BrowserLoginOpts` interfaces; `makeLoginRelay(relayBase: string): BrowserLoginDeps['relay']` from `login-relay-client.ts`. Task 5 wires these into `wallet login`. + +- [ ] **Step 1: Add vitest to the CLI package** + +In `packages/polygon-agent-cli/package.json`, add to `scripts`: + +```json +"test": "vitest run" +``` + +and to `devDependencies`: + +```json +"vitest": "^3.0.0" +``` + +Run: `pnpm install` + +- [ ] **Step 2: Write the failing tests** + +Create `packages/polygon-agent-cli/src/lib/browser-login.test.ts`: + +```ts +import { describe, expect, it } from 'vitest'; + +import { + runBrowserLogin, + type BrowserLoginDeps, + type BrowserLoginOpts, + type LoginAction, + type LoginStatus +} from './browser-login.ts'; + +// A scripted fake: nextAction() pops the queue (null = pending tick), and every +// published status is recorded for assertions. +function makeFakes(actionQueue: Array) { + const statuses: LoginStatus[] = []; + const calls: string[] = []; + let time = 0; + + const deps: BrowserLoginDeps = { + relay: { + registerSession: async () => { + calls.push('registerSession'); + }, + nextAction: async () => (actionQueue.length > 0 ? (actionQueue.shift() ?? null) : null), + setStatus: async (_s, status) => { + statuses.push(status); + }, + registerOidcHandoff: async (state, returnTo) => { + calls.push(`registerOidcHandoff:${state}:${returnTo}`); + }, + pollOidcCallback: async () => ({ code: 'CODE1', state: 'STATE1' }) + }, + wallet: { + startOidcRedirectAuth: async () => ({ url: 'https://accounts.google.com/auth', state: 'STATE1' }), + completeOidcRedirectAuth: async (p) => { + calls.push(`completeOidc:${p.callbackUrl}`); + return { walletAddress: '0xW' }; + }, + startEmailAuth: async (p) => { + calls.push(`startEmail:${p.email}`); + }, + completeEmailAuth: async (p) => { + calls.push(`completeEmail:${p.code}`); + if (p.code === 'BAD') throw new Error('invalid code'); + return { walletAddress: '0xW' }; + } + }, + announce: async (url) => { + calls.push(`announce:${url}`); + }, + sleep: async () => { + time += 1000; + }, + now: () => time, + randomSessionId: () => 'sessionid12345678' + }; + return { deps, statuses, calls }; +} + +const OPTS: BrowserLoginOpts = { + relayBase: 'https://relay.test', + uiBase: 'https://ui.test', + timeoutMs: 60_000 +}; + +describe('runBrowserLogin', () => { + it('completes the google flow', async () => { + const { deps, statuses, calls } = makeFakes([{ type: 'google' }]); + const result = await runBrowserLogin(deps, OPTS); + + expect(result).toEqual({ walletAddress: '0xW', loginMethod: 'google' }); + expect(calls).toContain('announce:https://ui.test/login#sessionid12345678'); + expect(calls).toContain('registerOidcHandoff:STATE1:https://ui.test/login#sessionid12345678'); + expect(calls).toContain('completeOidc:https://relay.test/api/oidc/cb?code=CODE1&state=STATE1'); + expect(statuses).toEqual([ + { status: 'auth-url', url: 'https://accounts.google.com/auth' }, + { status: 'done', walletAddress: '0xW' } + ]); + }); + + it('completes the email flow', async () => { + const { deps, statuses, calls } = makeFakes([ + { type: 'email', email: 'a@b.co' }, + { type: 'otp', code: '123456' } + ]); + const result = await runBrowserLogin(deps, OPTS); + + expect(result).toEqual({ walletAddress: '0xW', loginMethod: 'email' }); + expect(calls).toContain('startEmail:a@b.co'); + expect(calls).toContain('completeEmail:123456'); + expect(statuses).toEqual([{ status: 'otp-sent' }, { status: 'done', walletAddress: '0xW' }]); + }); + + it('publishes otp-invalid and accepts a retried code', async () => { + const { deps, statuses } = makeFakes([ + { type: 'email', email: 'a@b.co' }, + { type: 'otp', code: 'BAD' }, + { type: 'otp', code: '123456' } + ]); + const result = await runBrowserLogin(deps, OPTS); + + expect(result.loginMethod).toBe('email'); + expect(statuses).toEqual([ + { status: 'otp-sent' }, + { status: 'otp-invalid', attemptsLeft: 2 }, + { status: 'done', walletAddress: '0xW' } + ]); + }); + + it('fails after three bad codes', async () => { + const { deps, statuses } = makeFakes([ + { type: 'email', email: 'a@b.co' }, + { type: 'otp', code: 'BAD' }, + { type: 'otp', code: 'BAD' }, + { type: 'otp', code: 'BAD' } + ]); + await expect(runBrowserLogin(deps, OPTS)).rejects.toThrow(/too many invalid codes/i); + expect(statuses.at(-1)).toMatchObject({ status: 'error' }); + }); + + it('throws when the user cancels on the page', async () => { + const { deps, statuses } = makeFakes([{ type: 'cancel' }]); + await expect(runBrowserLogin(deps, OPTS)).rejects.toThrow(/cancelled/i); + expect(statuses.at(-1)).toMatchObject({ status: 'error' }); + }); + + it('times out when no action ever arrives', async () => { + const { deps } = makeFakes([]); + await expect(runBrowserLogin(deps, { ...OPTS, timeoutMs: 5000 })).rejects.toThrow(/timed out/i); + }); + + it('propagates a relay registration failure', async () => { + const { deps } = makeFakes([]); + deps.relay.registerSession = async () => { + throw new Error('Relay register failed (503)'); + }; + await expect(runBrowserLogin(deps, OPTS)).rejects.toThrow(/Relay register failed/); + }); +}); +``` + +Run: `pnpm --filter @polygonlabs/agent-cli test` +Expected: FAIL, cannot resolve `./browser-login.ts`. + +- [ ] **Step 3: Implement the loop** + +Create `packages/polygon-agent-cli/src/lib/browser-login.ts`: + +```ts +// The browser-login action loop: the branded page (agentconnect-ui /login) is +// the input surface, the relay carries user actions here, and this process +// drives the actual SDK auth so keys and the PKCE verifier never leave the +// machine. Pure orchestration over injected deps so it is unit-testable. + +export type LoginAction = + | { type: 'google' } + | { type: 'email'; email: string } + | { type: 'otp'; code: string } + | { type: 'cancel' }; + +export type LoginStatus = + | { status: 'awaiting-method' } + | { status: 'auth-url'; url: string } + | { status: 'otp-sent' } + | { status: 'otp-invalid'; attemptsLeft?: number } + | { status: 'done'; walletAddress: string } + | { status: 'error'; message: string }; + +export interface BrowserLoginDeps { + relay: { + registerSession(session: string): Promise; + nextAction(session: string): Promise; + setStatus(session: string, status: LoginStatus): Promise; + registerOidcHandoff(state: string, returnTo: string): Promise; + pollOidcCallback(state: string, timeoutMs: number): Promise<{ code: string; state: string }>; + }; + wallet: { + startOidcRedirectAuth(p: { + provider: 'google'; + redirectUri: string; + relayRedirectUri?: string; + }): Promise<{ url: string; state: string }>; + completeOidcRedirectAuth(p: { + callbackUrl: string; + walletSelection: 'automatic'; + }): Promise<{ walletAddress: string }>; + startEmailAuth(p: { email: string }): Promise; + completeEmailAuth(p: { + code: string; + walletSelection: 'automatic'; + }): Promise<{ walletAddress: string }>; + }; + announce(url: string): Promise; + sleep(ms: number): Promise; + now(): number; + randomSessionId(): string; +} + +export interface BrowserLoginOpts { + relayBase: string; + uiBase: string; + seqRelay?: string; + timeoutMs: number; + pollIntervalMs?: number; +} + +const MAX_OTP_ATTEMPTS = 3; + +export async function runBrowserLogin( + deps: BrowserLoginDeps, + opts: BrowserLoginOpts +): Promise<{ walletAddress: string; loginMethod: 'google' | 'email' }> { + const { relay, wallet } = deps; + const interval = opts.pollIntervalMs ?? 2000; + const session = deps.randomSessionId(); + const pageUrl = `${opts.uiBase}/login#${session}`; + const deadline = deps.now() + opts.timeoutMs; + + await relay.registerSession(session); + await deps.announce(pageUrl); + + // Publish a terminal error so the page does not sit on a spinner, then throw. + const fail = async (message: string): Promise => { + try { + await relay.setStatus(session, { status: 'error', message }); + } catch { + // Best-effort: the CLI error below is the source of truth. + } + throw new Error(message); + }; + + let otpFailures = 0; + + while (deps.now() < deadline) { + const action = await relay.nextAction(session); + if (!action) { + await deps.sleep(interval); + continue; + } + + if (action.type === 'cancel') { + return fail('Login cancelled in the browser.'); + } + + if (action.type === 'google') { + const { url, state } = await wallet.startOidcRedirectAuth({ + provider: 'google', + redirectUri: `${opts.relayBase}/api/oidc/cb`, + ...(opts.seqRelay ? { relayRedirectUri: opts.seqRelay } : {}) + }); + await relay.registerOidcHandoff(state, pageUrl); + await relay.setStatus(session, { status: 'auth-url', url }); + try { + const cb = await relay.pollOidcCallback(state, Math.max(deadline - deps.now(), 1)); + const callbackUrl = `${opts.relayBase}/api/oidc/cb?code=${encodeURIComponent(cb.code)}&state=${encodeURIComponent(cb.state)}`; + const result = await wallet.completeOidcRedirectAuth({ + callbackUrl, + walletSelection: 'automatic' + }); + await relay.setStatus(session, { status: 'done', walletAddress: result.walletAddress }); + return { walletAddress: result.walletAddress, loginMethod: 'google' }; + } catch (error) { + return fail((error as Error).message); + } + } + + if (action.type === 'email') { + try { + await wallet.startEmailAuth({ email: action.email }); + otpFailures = 0; + await relay.setStatus(session, { status: 'otp-sent' }); + } catch (error) { + return fail((error as Error).message); + } + continue; + } + + // action.type === 'otp' + try { + const result = await wallet.completeEmailAuth({ + code: action.code, + walletSelection: 'automatic' + }); + await relay.setStatus(session, { status: 'done', walletAddress: result.walletAddress }); + return { walletAddress: result.walletAddress, loginMethod: 'email' }; + } catch { + otpFailures += 1; + if (otpFailures >= MAX_OTP_ATTEMPTS) { + return fail('Login failed: too many invalid codes.'); + } + await relay.setStatus(session, { + status: 'otp-invalid', + attemptsLeft: MAX_OTP_ATTEMPTS - otpFailures + }); + } + } + + return fail('Timed out waiting for browser login. Re-run, or use `wallet login --local`.'); +} +``` + +- [ ] **Step 4: Run tests to verify they pass** + +Run: `pnpm --filter @polygonlabs/agent-cli test` +Expected: 7 passed. + +- [ ] **Step 5: Implement the HTTP relay client** + +Create `packages/polygon-agent-cli/src/lib/login-relay-client.ts`: + +```ts +// HTTP client for the relay's /api/login pairing routes (packages/oidc-relay). +// Produces the `relay` dependency for runBrowserLogin; the OIDC handoff pieces +// reuse the existing oidc-relay-client functions. + +import type { BrowserLoginDeps, LoginAction, LoginStatus } from './browser-login.ts'; +import { pollRelayForCallback, registerRelaySession } from './oidc-relay-client.ts'; + +export function makeLoginRelay(relayBase: string): BrowserLoginDeps['relay'] { + return { + async registerSession(session: string): Promise { + const res = await fetch(`${relayBase}/api/login/register`, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ session }) + }); + if (!res.ok && res.status !== 204) { + throw new Error( + `Relay register failed (${res.status}). Check POLYGON_AGENT_OIDC_RELAY / --relay-url, or use --local.` + ); + } + }, + + async nextAction(session: string): Promise { + const res = await fetch( + `${relayBase}/api/login/next-action?session=${encodeURIComponent(session)}` + ); + if (!res.ok) throw new Error(`Relay poll failed (${res.status})`); + const data = (await res.json()) as { state: string; action?: LoginAction }; + if (data.state === 'expired') { + throw new Error('Login session expired before completion. Re-run `wallet login`.'); + } + return data.state === 'action' && data.action ? data.action : null; + }, + + async setStatus(session: string, status: LoginStatus): Promise { + const res = await fetch(`${relayBase}/api/login/status`, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ session, status }) + }); + if (!res.ok && res.status !== 204) throw new Error(`Relay status update failed (${res.status})`); + }, + + registerOidcHandoff(state: string, returnTo: string): Promise { + return registerRelaySession(relayBase, state, returnTo); + }, + + pollOidcCallback(state: string, timeoutMs: number): Promise<{ code: string; state: string }> { + return pollRelayForCallback(relayBase, state, { timeoutMs }); + } + }; +} +``` + +- [ ] **Step 6: Add the returnTo parameter to `registerRelaySession`** + +In `packages/polygon-agent-cli/src/lib/oidc-relay-client.ts`, change the signature and body of `registerRelaySession`: + +```ts +export async function registerRelaySession( + relayBase: string, + state: string, + returnTo?: string +): Promise { + const res = await fetch(`${relayBase}/api/oidc/register`, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify(returnTo ? { state, returnTo } : { state }) + }); + if (!res.ok && res.status !== 204) { + throw new Error( + `Relay register failed (${res.status}). Check POLYGON_AGENT_OIDC_RELAY / --relay-url.` + ); + } +} +``` + +(The existing call site in `wallet.ts` passes two arguments and is unaffected.) + +- [ ] **Step 7: Typecheck, test, commit** + +```bash +pnpm --filter @polygonlabs/agent-cli typecheck && pnpm --filter @polygonlabs/agent-cli test +git add packages/polygon-agent-cli/src/lib/browser-login.ts packages/polygon-agent-cli/src/lib/browser-login.test.ts packages/polygon-agent-cli/src/lib/login-relay-client.ts packages/polygon-agent-cli/src/lib/oidc-relay-client.ts packages/polygon-agent-cli/package.json pnpm-lock.yaml +git commit -m "feat(cli): browser-login action loop and login relay client" +``` + +--- + +### Task 5: Wire browser login into `wallet login` and update docs + +**Files:** +- Modify: `packages/polygon-agent-cli/src/lib/oms-client.ts` (baked-in defaults, `loginUiBaseUrl`) +- Modify: `packages/polygon-agent-cli/src/commands/wallet.ts` (flags, handleLogin) +- Modify: `packages/polygon-agent-cli/README.md` (login section) +- Modify: `packages/polygon-agent-cli/skills/SKILL.md` (login section; this is the canonical copy) +- Modify: `CLAUDE.md` (wallet auth section) + +**Interfaces:** +- Consumes: `runBrowserLogin`, `makeLoginRelay` (Task 4); existing `announceAuthUrl`, `saveOmsWalletPointer`, `showFunding`, `getOmsClient`, `startOidcCallbackServer`. +- Produces: `wallet login` defaults to the browser flow; `--local` keeps the loopback flow; `oidcRelayBaseUrl(): string` (now never undefined) and `loginUiBaseUrl(): string` exported from `oms-client.ts`. + +- [ ] **Step 1: Bake in default relay and UI URLs** + +In `packages/polygon-agent-cli/src/lib/oms-client.ts`, replace `oidcRelayBaseUrl` and add `loginUiBaseUrl`: + +```ts +// Production defaults for the browser-login flow. The relay custom domain and +// the Sequence allowlist entry for its /api/oidc/cb are deploy prerequisites +// (see docs/superpowers/specs/2026-07-13-browser-login-design.md). Override per +// environment with POLYGON_AGENT_OIDC_RELAY / POLYGON_AGENT_LOGIN_UI. +const DEFAULT_OIDC_RELAY = 'https://oidc-relay.polygon.technology'; +const DEFAULT_LOGIN_UI = 'https://agentconnect.polygon.technology'; + +/** + * Base URL of OUR OIDC handoff + login relay (packages/oidc-relay). Read from + * POLYGON_AGENT_OIDC_RELAY with a production default; `--relay-url` overrides + * per-run. Trailing slash trimmed so callers can append `/api/...` cleanly. + */ +export function oidcRelayBaseUrl(): string { + const v = process.env.POLYGON_AGENT_OIDC_RELAY; + return v ? v.replace(/\/+$/, '') : DEFAULT_OIDC_RELAY; +} + +/** Base URL of the agentconnect login page. POLYGON_AGENT_LOGIN_UI overrides. */ +export function loginUiBaseUrl(): string { + const v = process.env.POLYGON_AGENT_LOGIN_UI; + return v ? v.replace(/\/+$/, '') : DEFAULT_LOGIN_UI; +} +``` + +(Keep `oidcRelayRedirectUri()` as is.) + +- [ ] **Step 2: Rework `handleLogin` in `wallet.ts`** + +In `packages/polygon-agent-cli/src/commands/wallet.ts`: + +Update imports: + +```ts +import { randomBytes } from 'node:crypto'; + +import { runBrowserLogin } from '../lib/browser-login.ts'; +import { makeLoginRelay } from '../lib/login-relay-client.ts'; +import { startOidcCallbackServer } from '../lib/oidc-callback-server.ts'; +import { getOmsClient, loginUiBaseUrl, oidcRelayBaseUrl, oidcRelayRedirectUri } from '../lib/oms-client.ts'; +``` + +(`registerRelaySession`/`pollRelayForCallback` are no longer imported here; the old `--remote` branch goes away.) + +Update `LoginArgs`: + +```ts +interface LoginArgs { + name: string; + provider: string; + port: number; + timeout: number; + force: boolean; + fund: boolean; + local: boolean; + remote: boolean; + relayUrl?: string; +} +``` + +Replace `obtainBrowserCallbackUrl` with a loopback-only version (the relay-polling branch is superseded by the browser flow): + +```ts +// Legacy --local flow: a short-lived loopback server; the relay bounces the +// browser to it. Only works when the browser runs on this machine. +async function obtainLoopbackCallbackUrl( + oms: ReturnType, + provider: 'google', + argv: LoginArgs +): Promise { + const seqRelay = oidcRelayRedirectUri(); + const server = await startOidcCallbackServer({ + port: argv.port, + timeoutMs: argv.timeout * 1000 + }); + try { + const { url } = await oms.wallet.startOidcRedirectAuth({ + provider, + redirectUri: server.redirectUri, + ...(seqRelay ? { relayRedirectUri: seqRelay } : {}) + }); + await announceAuthUrl(url); + return await server.waitForCallbackUrl; + } finally { + server.close(); + } +} +``` + +Replace `handleLogin` with: + +```ts +async function handleLogin(argv: LoginArgs): Promise { + try { + const oms = getOmsClient(argv.name); + + // Short-circuit if already logged in (the SDK restores the session from + // storage on construction). Starting a new auth would clearSession(), so + // re-login is opt-in via --force. + if (!argv.force && oms.wallet.walletAddress) { + jsonOut({ + ok: true, + walletName: argv.name, + walletAddress: oms.wallet.walletAddress, + alreadyLoggedIn: true + }); + return; + } + + let walletAddress: string; + let loginMethod: string; + + if (argv.local) { + if (argv.provider !== 'google') { + throw new Error(`Unsupported provider "${argv.provider}". Only "google" works with --local.`); + } + const callbackUrl = await obtainLoopbackCallbackUrl(oms, 'google', argv); + const result = await oms.wallet.completeOidcRedirectAuth({ + callbackUrl, + walletSelection: 'automatic' + }); + walletAddress = result.walletAddress; + loginMethod = 'google'; + } else { + if (argv.remote) { + process.stderr.write('--remote is deprecated: the default login already works remotely.\n'); + } + const relayBase = argv.relayUrl?.replace(/\/+$/, '') || oidcRelayBaseUrl(); + const result = await runBrowserLogin( + { + relay: makeLoginRelay(relayBase), + wallet: oms.wallet, + announce: announceAuthUrl, + sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)), + now: () => Date.now(), + randomSessionId: () => randomBytes(16).toString('base64url') + }, + { + relayBase, + uiBase: loginUiBaseUrl(), + seqRelay: oidcRelayRedirectUri(), + timeoutMs: argv.timeout * 1000 + } + ); + walletAddress = result.walletAddress; + loginMethod = result.loginMethod; + } + + await saveOmsWalletPointer(argv.name, { + walletAddress, + loginMethod, + createdAt: new Date().toISOString() + }); + + jsonOut({ ok: true, walletName: argv.name, walletAddress, loginMethod }); + + // Funding: the login page's success screen already directs the user onward, + // so the browser flow only prints the panel; --local keeps opening the page. + if (argv.fund !== false) { + await showFunding(argv.name, walletAddress, 137, { openBrowser: argv.local }); + } + } catch (error) { + jsonOut({ ok: false, error: (error as Error).message }); + process.exit(1); + } +} +``` + +Type note: `oms.wallet` satisfies `BrowserLoginDeps['wallet']` structurally (the SDK methods accept supersets of the params and return supersets of the results). If tsc complains about the overloaded `completeEmailAuth`/`completeOidcRedirectAuth`, wrap the two methods explicitly: + +```ts + wallet: { + startOidcRedirectAuth: (p) => oms.wallet.startOidcRedirectAuth(p), + completeOidcRedirectAuth: (p) => oms.wallet.completeOidcRedirectAuth(p), + startEmailAuth: (p) => oms.wallet.startEmailAuth(p), + completeEmailAuth: (p) => oms.wallet.completeEmailAuth(p) + }, +``` + +- [ ] **Step 3: Update the yargs login builder** + +In the `wallet login` command builder in `wallet.ts`: + +- `describe` for `login`: `'Log in in the browser (choose Google or email on the login page)'` +- `provider` option describe: `'OIDC provider for --local (the browser flow picks the method on the page)'` +- `timeout` default: `600`, describe: `'Seconds to wait for the browser login before giving up'` +- `remote` option describe: `'(deprecated) the default flow already works remotely'` +- Add after the `remote` option: + +```ts + .option('local', { + type: 'boolean', + default: false, + describe: + 'Legacy loopback flow: raw Google URL + localhost callback (browser must be on this machine)' + }) +``` + +- `relay-url` describe: `'Relay base URL (overrides POLYGON_AGENT_OIDC_RELAY)'` + +- [ ] **Step 4: Typecheck, test, and smoke-check the fallback** + +```bash +pnpm --filter @polygonlabs/agent-cli typecheck && pnpm --filter @polygonlabs/agent-cli test +tsx packages/polygon-agent-cli/src/index.ts wallet login --help +``` + +Expected: help shows `--local`, `--remote` marked deprecated, timeout default 600. + +Smoke-check the browser flow against the local relay from Task 2 (no real login, just the announce + poll wiring): + +```bash +cd packages/oidc-relay && npx -y wrangler@3 dev --port 8788 & +sleep 8 +cd ../.. +POLYGON_AGENT_OIDC_RELAY=http://localhost:8788 POLYGON_AGENT_LOGIN_UI=http://localhost:5173 \ + timeout 15 tsx packages/polygon-agent-cli/src/index.ts wallet login --name plan-smoke --timeout 10 --no-fund +kill %1 +``` + +Expected: prints `Open this URL to sign in:` with `http://localhost:5173/login#<22-char id>`, then times out after ~10s with `{"ok":false,"error":"Timed out waiting for browser login. Re-run, or use `wallet login --local`."}`. (Requires `SEQUENCE_PUBLISHABLE_KEY` configured, as any login does. Clean up with `rm -rf ~/.polygon-agent/oms/plan-smoke ~/.polygon-agent/wallets/plan-smoke.json` if created.) + +- [ ] **Step 5: Update docs** + +- `packages/polygon-agent-cli/README.md`: in the wallet login section, describe the new default (browser page with Google or email, works local and remote), the `--local` fallback, the `--remote` deprecation, and the `POLYGON_AGENT_LOGIN_UI` env var. +- `packages/polygon-agent-cli/skills/SKILL.md`: update the `wallet login` command description the same way (canonical copy only). +- `CLAUDE.md` (repo root): update the "Wallet auth (OMS V3)" bullet: login opens the agentconnect login page by default (Google or email chosen there); `--local` is the loopback fallback; `--remote` deprecated. + +No em dashes in any of the new copy. + +- [ ] **Step 6: Commit** + +```bash +git add packages/polygon-agent-cli/src/commands/wallet.ts packages/polygon-agent-cli/src/lib/oms-client.ts packages/polygon-agent-cli/README.md packages/polygon-agent-cli/skills/SKILL.md CLAUDE.md +git commit -m "feat(cli): wallet login defaults to the agentconnect browser flow" +``` + +--- + +### Task 6: UI login state machine with tests + +**Files:** +- Create: `packages/agentconnect-ui/src/login/machine.ts` +- Test: `packages/agentconnect-ui/src/login/machine.test.ts` +- Modify: `packages/agentconnect-ui/package.json` (vitest devDep + test script) + +**Interfaces:** +- Consumes: nothing (pure reducer). +- Produces: `MachineState`, `MachineEvent`, `reduce(state, event): MachineState`, `initialState`; `RelayStatus` type (LoginStatus plus `{status:'expired'}`). Task 7's component drives this. + +- [ ] **Step 1: Add vitest to agentconnect-ui** + +In `packages/agentconnect-ui/package.json`, add to `scripts`: + +```json +"test": "vitest run" +``` + +and to `devDependencies`: + +```json +"vitest": "^3.0.0" +``` + +Run: `pnpm install` + +- [ ] **Step 2: Write the failing tests** + +Create `packages/agentconnect-ui/src/login/machine.test.ts`: + +```ts +import { describe, expect, it } from 'vitest'; + +import { initialState, reduce, type MachineState } from './machine.ts'; + +describe('login machine', () => { + it('google: method -> google-wait -> success', () => { + let s: MachineState = initialState; + s = reduce(s, { type: 'choose-google' }); + expect(s).toEqual({ kind: 'google-wait' }); + s = reduce(s, { type: 'status', status: { status: 'done', walletAddress: '0xW' } }); + expect(s).toEqual({ kind: 'success', walletAddress: '0xW' }); + }); + + it('email: full path with an otp retry', () => { + let s: MachineState = initialState; + s = reduce(s, { type: 'choose-email' }); + expect(s).toEqual({ kind: 'email-entry' }); + s = reduce(s, { type: 'submit-email', email: 'a@b.co' }); + expect(s).toEqual({ kind: 'email-wait', email: 'a@b.co' }); + s = reduce(s, { type: 'status', status: { status: 'otp-sent' } }); + expect(s).toEqual({ kind: 'otp-entry', email: 'a@b.co' }); + s = reduce(s, { type: 'submit-otp', code: '111111' }); + expect(s).toEqual({ kind: 'otp-wait', email: 'a@b.co' }); + s = reduce(s, { type: 'status', status: { status: 'otp-invalid', attemptsLeft: 2 } }); + expect(s).toEqual({ kind: 'otp-entry', email: 'a@b.co', attemptsLeft: 2, invalid: true }); + s = reduce(s, { type: 'submit-otp', code: '222222' }); + s = reduce(s, { type: 'status', status: { status: 'done', walletAddress: '0xW' } }); + expect(s).toEqual({ kind: 'success', walletAddress: '0xW' }); + }); + + it('expired and error statuses are terminal from any state', () => { + expect(reduce(initialState, { type: 'status', status: { status: 'expired' } })).toEqual({ + kind: 'expired' + }); + expect( + reduce({ kind: 'otp-wait', email: 'a@b.co' }, { type: 'status', status: { status: 'error', message: 'boom' } }) + ).toEqual({ kind: 'failed', message: 'boom' }); + }); + + it('reconciles a refreshed page from the polled status', () => { + // After a refresh the page is back at `method`; the poll snaps it forward. + expect(reduce(initialState, { type: 'status', status: { status: 'otp-sent' } })).toEqual({ + kind: 'otp-entry', + email: '' + }); + expect( + reduce(initialState, { type: 'status', status: { status: 'done', walletAddress: '0xW' } }) + ).toEqual({ kind: 'success', walletAddress: '0xW' }); + }); + + it('back returns from email entry to method choice', () => { + expect(reduce({ kind: 'email-entry' }, { type: 'back' })).toEqual({ kind: 'method' }); + }); + + it('awaiting-method and stale statuses do not regress the ui', () => { + expect( + reduce({ kind: 'email-entry' }, { type: 'status', status: { status: 'awaiting-method' } }) + ).toEqual({ kind: 'email-entry' }); + // auth-url is handled as a side effect (redirect); state is unchanged. + expect( + reduce({ kind: 'google-wait' }, { type: 'status', status: { status: 'auth-url', url: 'https://x' } }) + ).toEqual({ kind: 'google-wait' }); + }); +}); +``` + +Run: `pnpm --filter @polygonlabs/agentconnect-ui test` +Expected: FAIL, cannot resolve `./machine.ts`. + +- [ ] **Step 3: Implement the machine** + +Create `packages/agentconnect-ui/src/login/machine.ts`: + +```ts +// Pure state machine for the /login page. The component polls the relay and +// feeds statuses in as events alongside user input; side effects (posting +// actions, redirecting to the auth url) live in the component, not here. + +export type LoginStatus = + | { status: 'awaiting-method' } + | { status: 'auth-url'; url: string } + | { status: 'otp-sent' } + | { status: 'otp-invalid'; attemptsLeft?: number } + | { status: 'done'; walletAddress: string } + | { status: 'error'; message: string }; + +export type RelayStatus = LoginStatus | { status: 'expired' }; + +export type MachineState = + | { kind: 'method' } + | { kind: 'google-wait' } + | { kind: 'email-entry' } + | { kind: 'email-wait'; email: string } + | { kind: 'otp-entry'; email: string; invalid?: boolean; attemptsLeft?: number } + | { kind: 'otp-wait'; email: string } + | { kind: 'success'; walletAddress: string } + | { kind: 'expired' } + | { kind: 'failed'; message: string }; + +export type MachineEvent = + | { type: 'status'; status: RelayStatus } + | { type: 'choose-google' } + | { type: 'choose-email' } + | { type: 'submit-email'; email: string } + | { type: 'submit-otp'; code: string } + | { type: 'back' }; + +export const initialState: MachineState = { kind: 'method' }; + +function emailOf(state: MachineState): string { + return 'email' in state ? state.email : ''; +} + +export function reduce(state: MachineState, event: MachineEvent): MachineState { + if (event.type === 'status') { + const s = event.status; + // Terminal statuses win from anywhere. + if (s.status === 'expired') return { kind: 'expired' }; + if (s.status === 'error') return { kind: 'failed', message: s.message }; + if (s.status === 'done') return { kind: 'success', walletAddress: s.walletAddress }; + // otp-sent snaps forward (also reconciles a refreshed page). + if (s.status === 'otp-sent') { + if (state.kind === 'otp-entry' || state.kind === 'otp-wait') return state; + return { kind: 'otp-entry', email: emailOf(state) }; + } + if (s.status === 'otp-invalid' && state.kind === 'otp-wait') { + return { kind: 'otp-entry', email: state.email, invalid: true, attemptsLeft: s.attemptsLeft }; + } + // awaiting-method and auth-url never regress the ui. + return state; + } + + switch (event.type) { + case 'choose-google': + return state.kind === 'method' ? { kind: 'google-wait' } : state; + case 'choose-email': + return state.kind === 'method' ? { kind: 'email-entry' } : state; + case 'submit-email': + return state.kind === 'email-entry' ? { kind: 'email-wait', email: event.email } : state; + case 'submit-otp': + return state.kind === 'otp-entry' ? { kind: 'otp-wait', email: state.email } : state; + case 'back': + return state.kind === 'email-entry' ? { kind: 'method' } : state; + } +} +``` + +- [ ] **Step 4: Run tests to verify they pass** + +Run: `pnpm --filter @polygonlabs/agentconnect-ui test` +Expected: 6 passed. + +- [ ] **Step 5: Typecheck and commit** + +```bash +pnpm --filter @polygonlabs/agentconnect-ui typecheck +git add packages/agentconnect-ui/src/login/machine.ts packages/agentconnect-ui/src/login/machine.test.ts packages/agentconnect-ui/package.json pnpm-lock.yaml +git commit -m "feat(agentconnect-ui): login page state machine" +``` + +--- + +### Task 7: LoginPage component, route, and config + +**Files:** +- Create: `packages/agentconnect-ui/src/login/LoginPage.tsx` +- Modify: `packages/agentconnect-ui/src/App.tsx` (route on `/login`, export `LogoBadge`) +- Modify: `packages/agentconnect-ui/src/config.ts` (relay URL) +- Modify: `packages/agentconnect-ui/.env.example` (document `VITE_OIDC_RELAY_URL`) + +**Interfaces:** +- Consumes: `reduce`/`initialState`/types from Task 6; relay routes from Task 2; `LogoBadge` from `App.tsx`. +- Produces: `LoginPage` component rendered when `window.location.pathname === '/login'`. + +- [ ] **Step 1: Add the relay URL to config** + +In `packages/agentconnect-ui/src/config.ts`, append: + +```ts +// oidc-relay base URL for the /login pairing session (per-environment secret). +export const oidcRelayUrl = + (import.meta.env.VITE_OIDC_RELAY_URL as string | undefined) ?? + 'https://oidc-relay.polygon.technology'; +``` + +Add to `packages/agentconnect-ui/.env.example`: + +``` +VITE_OIDC_RELAY_URL=https://oidc-relay.polygon.technology +``` + +- [ ] **Step 2: Export `LogoBadge` from App.tsx** + +In `packages/agentconnect-ui/src/App.tsx`, find the `LogoBadge` function component and add `export` to its declaration (`function LogoBadge` becomes `export function LogoBadge`), leaving its body unchanged. + +- [ ] **Step 3: Create the LoginPage component** + +Create `packages/agentconnect-ui/src/login/LoginPage.tsx`. Follow the existing visual language of App.tsx: `#f5f6fb` page background, `#141635` primary, white cards with `rounded-2xl` and the same shadow treatment, `LogoBadge` fixed top-center. All copy in sentence case, no em dashes. + +```tsx +import { useCallback, useEffect, useRef, useState } from 'react'; + +import { LogoBadge } from '../App.js'; +import { oidcRelayUrl } from '../config'; +import { + initialState, + reduce, + type MachineEvent, + type MachineState, + type RelayStatus +} from './machine.js'; + +const WALLET_URL = 'https://wallet.polygon.technology'; +const POLL_MS = 1500; + +type LoginAction = + | { type: 'google' } + | { type: 'email'; email: string } + | { type: 'otp'; code: string } + | { type: 'cancel' }; + +async function postAction(session: string, action: LoginAction): Promise { + await fetch(`${oidcRelayUrl}/api/login/action`, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ session, action }) + }); +} + +async function fetchStatus(session: string): Promise { + const res = await fetch(`${oidcRelayUrl}/api/login/status?session=${encodeURIComponent(session)}`); + if (!res.ok) return { status: 'expired' }; + return (await res.json()) as RelayStatus; +} + +const TERMINAL: MachineState['kind'][] = ['success', 'expired', 'failed']; + +export function LoginPage() { + const session = window.location.hash.slice(1); + const [state, setState] = useState(initialState); + const dispatch = useCallback((event: MachineEvent) => { + setState((s) => reduce(s, event)); + }, []); + const redirected = useRef(false); + + // Poll the relay for CLI-published status; redirect once when the auth url + // arrives (a side effect the reducer deliberately does not model). + useEffect(() => { + if (!session || TERMINAL.includes(state.kind)) return; + const timer = setInterval(() => { + void fetchStatus(session).then((status) => { + if (status.status === 'auth-url' && !redirected.current && state.kind === 'google-wait') { + redirected.current = true; + window.location.assign(status.url); + return; + } + dispatch({ type: 'status', status }); + }); + }, POLL_MS); + return () => clearInterval(timer); + }, [session, state.kind, dispatch]); + + if (!session) { + return ( + +

No login session

+

+ Open this page from the polygon-agent CLI: run + polygon-agent wallet login + in your terminal. +

+
+ ); + } + + return {renderState(state, session, dispatch)}; +} + +function Shell({ children }: { children: React.ReactNode }) { + return ( +
+
+ +
+
+ {children} +
+
+ ); +} + +function renderState( + state: MachineState, + session: string, + dispatch: (e: MachineEvent) => void +) { + switch (state.kind) { + case 'method': + return ( + { + void postAction(session, { type: 'google' }); + dispatch({ type: 'choose-google' }); + }} + onEmail={() => dispatch({ type: 'choose-email' })} + onCancel={() => { + // The CLI consumes the cancel, publishes an error status, and exits; + // the next poll moves this page to the failed state. + void postAction(session, { type: 'cancel' }); + }} + /> + ); + case 'google-wait': + return ; + case 'email-entry': + return ( + { + void postAction(session, { type: 'email', email }); + dispatch({ type: 'submit-email', email }); + }} + onBack={() => dispatch({ type: 'back' })} + /> + ); + case 'email-wait': + return ; + case 'otp-entry': + return ( + { + void postAction(session, { type: 'otp', code }); + dispatch({ type: 'submit-otp', code }); + }} + /> + ); + case 'otp-wait': + return ; + case 'success': + return ( +
+

You're signed in

+

Wallet {state.walletAddress}

+

+ Your terminal session is ready. You can close this tab. +

+ + Manage your wallet + +
+ ); + case 'expired': + return ( +
+

This link has expired

+

+ Run polygon-agent wallet login again + to get a fresh link. +

+
+ ); + case 'failed': + return ( +
+

Sign in failed

+

{state.message}

+

Check your terminal for details and re-run the login.

+
+ ); + } +} + +function MethodChoice({ + onGoogle, + onEmail, + onCancel +}: { + onGoogle: () => void; + onEmail: () => void; + onCancel: () => void; +}) { + return ( +
+

Sign in to your agent wallet

+

+ This connects the polygon-agent CLI in your terminal. +

+ + + +
+ ); +} + +function EmailForm({ onSubmit, onBack }: { onSubmit: (email: string) => void; onBack: () => void }) { + const [email, setEmail] = useState(''); + return ( +
{ + e.preventDefault(); + if (email.includes('@')) onSubmit(email.trim()); + }} + > +

Sign in with email

+ setEmail(e.target.value)} + placeholder="you@example.com" + className="mt-6 w-full rounded-xl border border-[#c8cfe1] px-4 py-3 text-sm text-[#141635] outline-none focus:border-[#141635]" + /> + + +
+ ); +} + +function OtpForm({ + invalid, + attemptsLeft, + onSubmit +}: { + invalid?: boolean; + attemptsLeft?: number; + onSubmit: (code: string) => void; +}) { + const [code, setCode] = useState(''); + return ( +
{ + e.preventDefault(); + if (code.trim().length >= 4) onSubmit(code.trim()); + }} + > +

Enter your code

+

We sent a one-time code to your email.

+ {invalid && ( +

+ That code didn't work{typeof attemptsLeft === 'number' ? ` (${attemptsLeft} attempts left)` : ''}. Try again. +

+ )} + setCode(e.target.value)} + placeholder="123456" + className="mt-6 w-full rounded-xl border border-[#c8cfe1] px-4 py-3 text-center text-lg tracking-[0.3em] text-[#141635] outline-none focus:border-[#141635]" + /> + +
+ ); +} + +function Waiting({ text }: { text: string }) { + return ( +
+
+

{text}

+
+ ); +} +``` + +`LogoBadge` takes no props (it renders the Polygon logo plus the `>_ agent` chip at `App.tsx:169`); the import works once Step 2's `export` keyword is added. + +- [ ] **Step 4: Route `/login` in App.tsx** + +In `packages/agentconnect-ui/src/App.tsx`, add the import: + +```tsx +import { LoginPage } from './login/LoginPage.js'; +``` + +and at the top of the `App` function body (before the `params` memo): + +```tsx + if (window.location.pathname === '/login') { + return ; + } +``` + +- [ ] **Step 5: Typecheck, lint, and verify in the browser** + +```bash +pnpm --filter @polygonlabs/agentconnect-ui typecheck && pnpm --filter @polygonlabs/agentconnect-ui lint +``` + +Manual verification against the local relay: + +```bash +cd packages/oidc-relay && npx -y wrangler@3 dev --port 8788 & +cd ../agentconnect-ui && VITE_OIDC_RELAY_URL=http://localhost:8788 pnpm dev & +sleep 8 +# Register a session like the CLI would: +curl -s -X POST localhost:8788/api/login/register -H 'content-type: application/json' -d '{"session":"uitest1234567890"}' -o /dev/null +``` + +Open `http://localhost:5173/login#uitest1234567890`: +- Method choice renders with both buttons. +- Click "Continue with email", submit an address, page shows the waiting spinner. +- Simulate the CLI: `curl -s -X POST localhost:8788/api/login/status -H 'content-type: application/json' -d '{"session":"uitest1234567890","status":{"status":"otp-sent"}}'` and the OTP input appears. +- Simulate completion: `curl -s -X POST localhost:8788/api/login/status -H 'content-type: application/json' -d '{"session":"uitest1234567890","status":{"status":"done","walletAddress":"0xabc"}}'` and the success screen appears with the wallet.polygon.technology button. +- `http://localhost:5173/login` (no hash) shows the "No login session" notice. +- Fresh session + "Cancel this login": `curl -s "localhost:8788/api/login/next-action?session="` returns the cancel action (this is what the CLI consumes). +- `http://localhost:5173/?wallet=0xabc` still renders the dashboard (route untouched). + +Kill both dev servers when done. + +- [ ] **Step 6: Commit** + +```bash +git add packages/agentconnect-ui/src/login/LoginPage.tsx packages/agentconnect-ui/src/App.tsx packages/agentconnect-ui/src/config.ts packages/agentconnect-ui/.env.example +git commit -m "feat(agentconnect-ui): /login page for the browser login flow" +``` + +--- + +### Task 8: Staging end-to-end and production checklist + +**Files:** +- No new source files; deploys and verification. Possible small fixes discovered here get their own commits. + +**Interfaces:** +- Consumes: everything above. +- Produces: verified staging flow; a ticked production checklist. + +- [ ] **Step 1: Deploy the relay and UI to staging** + +```bash +pnpm --filter @polygonlabs/oidc-relay deploy:staging +pnpm --filter @polygonlabs/agentconnect-ui deploy:staging +``` + +Note the staging relay URL (workers.dev) from the wrangler output. The staging UI build must have `VITE_OIDC_RELAY_URL` set to it (GitHub Environments secret, or build locally with the env var before deploying). + +- [ ] **Step 2: End-to-end Google login (human in the loop)** + +```bash +POLYGON_AGENT_OIDC_RELAY=https://oidc-relay-staging..workers.dev \ +POLYGON_AGENT_LOGIN_UI=https://agentconnect.staging.polygon.technology \ + tsx packages/polygon-agent-cli/src/index.ts wallet login --name e2e-google --force --no-fund +``` + +Verify: the printed URL opens the branded page; Continue with Google round-trips through Google and lands back on the page; page shows the success state with the wallet address and the wallet.polygon.technology button; the CLI prints `{"ok":true,...,"loginMethod":"google"}`. + +- [ ] **Step 3: End-to-end email login (human in the loop)** + +Same command with `--name e2e-email`. On the page choose email, enter a real inbox, type the received code. Verify one deliberate wrong code first: the page shows the invalid-code message with attempts left, then the right code succeeds and the CLI prints `loginMethod":"email"`. + +- [ ] **Step 4: Regression-check the fallback and expiry** + +- `wallet login --local --name e2e-local --no-fund`: old loopback flow works unchanged. +- Start a login, wait 10+ minutes without touching the page, confirm the CLI times out cleanly and the page shows the expired state on next poll. +- Clean up test wallets: `wallet remove --name e2e-google` etc. + +- [ ] **Step 5: Production checklist (record ticks in the PR description)** + +- [ ] Enable the relay production custom domain in `packages/oidc-relay/wrangler.toml` (uncomment/set `routes`, e.g. `oidc-relay.polygon.technology`) and deploy. +- [ ] Ask Sequence to allowlist `https://oidc-relay.polygon.technology/api/oidc/cb` as a redirect target (same process as the staging/localhost adds). +- [ ] Confirm the CLI defaults in `oms-client.ts` match the deployed domains. +- [ ] Set `VITE_OIDC_RELAY_URL` in the production GitHub Environment and deploy agentconnect production. +- [ ] Full production smoke: one Google login, one email login, from a machine that is not the deploy machine. diff --git a/docs/superpowers/plans/2026-07-14-zero-setup-onboarding.md b/docs/superpowers/plans/2026-07-14-zero-setup-onboarding.md new file mode 100644 index 0000000..cd0ccbe --- /dev/null +++ b/docs/superpowers/plans/2026-07-14-zero-setup-onboarding.md @@ -0,0 +1,486 @@ +# Zero-Setup Onboarding Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** `polygon-agent wallet login` becomes the entire onboarding: the CLI ships a default publishable key, and a successful login auto-provisions a Sequence Builder project + access key into `builder.json`. + +**Architecture:** Three small moves. (1) `loadOmsConfig` falls back to a baked-in default publishable key so `getOmsClient` always constructs. (2) The Builder HTTP helpers move from the ink UI file into a lib module. (3) A new `ensureBuilderAccessKey` lib (dependency-injected, unit-tested) runs best-effort after login, reusing the existing ephemeral-EOA ETHAuth flow from `setup`. Spec: `docs/superpowers/specs/2026-07-14-zero-setup-onboarding-design.md`. + +**Tech Stack:** TypeScript CLI (yargs, es2023), ethers (existing), vitest (already set up in this package). + +## Global Constraints + +- Conventional commit messages with package scope; never add a Co-Authored-By trailer. The pre-commit hook runs `pnpm -r run typecheck`. +- No em dashes in any new copy (docs, CLI strings, comments); sentence case. +- Canonical skill docs live in the repo-root `skills/` tree only; never create `packages/polygon-agent-cli/skills/`. +- Provisioning must NEVER fail or slow a successful login beyond its own network calls: every failure is caught, reported on stderr, and reflected as `builderProvisioned: false` in the login JSON. +- The default publishable key is the sandbox key from this machine's `~/.polygon-agent/builder.json` (`publishableKey` field, starts `pk_sdbx_01kqfw9z`); the implementer reads the full value from that file. Swapping it to a production key is a release-checklist item, not code in this plan. +- Existing users' `builder.json` (with accessKey already present) must be untouched by login. + +--- + +### Task 1: Move Builder HTTP helpers into a lib module + +**Files:** +- Create: `packages/polygon-agent-cli/src/lib/builder-api.ts` +- Modify: `packages/polygon-agent-cli/src/commands/setup-ui.tsx` (delete the three helpers, import from lib) +- Modify: `packages/polygon-agent-cli/src/commands/setup.ts` (import from lib) + +**Interfaces:** +- Consumes: nothing new. +- Produces: `getAuthToken(proofString: string): Promise`, `createProject(name: string, jwtToken: string): Promise<{ id: number; name: string }>`, `getDefaultAccessKey(projectId: number, jwtToken: string): Promise` exported from `lib/builder-api.ts`. Task 3 imports them. + +- [ ] **Step 1: Create the lib module** + +Create `packages/polygon-agent-cli/src/lib/builder-api.ts` with a header comment and the three functions moved VERBATIM from `packages/polygon-agent-cli/src/commands/setup-ui.tsx` (they are the top-of-file exports `getAuthToken`, `createProject`, `getDefaultAccessKey`; each reads `process.env.SEQUENCE_BUILDER_API_URL || 'https://api.sequence.build'`). Header comment: + +```ts +// Sequence Builder API helpers (GetAuthToken / CreateProject / GetDefaultAccessKey). +// Used by `setup` and by the post-login auto-provisioning in lib/builder-provision.ts. +``` + +- [ ] **Step 2: Update the two import sites** + +- In `setup-ui.tsx`: delete the three function bodies and their now-unused imports if any; add `export { getAuthToken, createProject, getDefaultAccessKey } from '../lib/builder-api.ts';` so any other consumer keeps working. +- In `setup.ts`: change the import line `import { SetupUI, getAuthToken, createProject, getDefaultAccessKey } from './setup-ui.js';` to import the three helpers from `../lib/builder-api.ts` and keep `SetupUI` from `./setup-ui.js`. + +- [ ] **Step 3: Verify and commit** + +Run: `pnpm --filter @polygonlabs/agent-cli typecheck && pnpm --filter @polygonlabs/agent-cli test` +Expected: typecheck clean, 9/9 tests pass (pure move, no behavior change). + +```bash +git add packages/polygon-agent-cli/src/lib/builder-api.ts packages/polygon-agent-cli/src/commands/setup-ui.tsx packages/polygon-agent-cli/src/commands/setup.ts +git commit -m "refactor(cli): move Builder API helpers into lib/builder-api" +``` + +--- + +### Task 2: Default publishable key in loadOmsConfig, with tests + +**Files:** +- Modify: `packages/polygon-agent-cli/src/lib/storage.ts` (`loadOmsConfig`) +- Modify: `packages/polygon-agent-cli/src/lib/oms-client.ts` (drop the unreachable not-configured error) +- Test: `packages/polygon-agent-cli/src/lib/oms-config.test.ts` + +**Interfaces:** +- Consumes: existing `OmsConfig` type, `loadOmsConfig(): OmsConfig | null`. +- Produces: `loadOmsConfig(): OmsConfig` (never null) and exported `DEFAULT_SEQUENCE_PUBLISHABLE_KEY` from storage.ts. `getOmsClient` no longer throws for missing config. + +- [ ] **Step 1: Write the failing tests** + +Create `packages/polygon-agent-cli/src/lib/oms-config.test.ts`. Storage computes its dir from `os.homedir()` at import time, so each case stubs `HOME` and imports a FRESH module copy: + +```ts +import { afterEach, describe, expect, it, vi } from 'vitest'; + +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; + +async function freshStorage(home: string) { + vi.resetModules(); + vi.stubEnv('HOME', home); + return await import('./storage.ts'); +} + +describe('loadOmsConfig resolution order', () => { + afterEach(() => { + vi.unstubAllEnvs(); + vi.resetModules(); + }); + + it('falls back to the baked-in default when neither env nor file exist', async () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), 'pa-home-')); + vi.stubEnv('SEQUENCE_PUBLISHABLE_KEY', ''); + const storage = await freshStorage(home); + const cfg = storage.loadOmsConfig(); + expect(cfg.publishableKey).toBe(storage.DEFAULT_SEQUENCE_PUBLISHABLE_KEY); + expect(cfg.publishableKey.startsWith('pk_')).toBe(true); + }); + + it('prefers builder.json over the default', async () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), 'pa-home-')); + fs.mkdirSync(path.join(home, '.polygon-agent'), { recursive: true }); + fs.writeFileSync( + path.join(home, '.polygon-agent', 'builder.json'), + JSON.stringify({ publishableKey: 'pk_test_fromfile' }) + ); + vi.stubEnv('SEQUENCE_PUBLISHABLE_KEY', ''); + const storage = await freshStorage(home); + expect(storage.loadOmsConfig().publishableKey).toBe('pk_test_fromfile'); + }); + + it('prefers the env var over everything', async () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), 'pa-home-')); + vi.stubEnv('SEQUENCE_PUBLISHABLE_KEY', 'pk_test_fromenv'); + const storage = await freshStorage(home); + expect(storage.loadOmsConfig().publishableKey).toBe('pk_test_fromenv'); + }); +}); +``` + +Note: the empty-string stub for `SEQUENCE_PUBLISHABLE_KEY` matters because the developer shell may have it set; `loadOmsConfig` treats empty as unset (it already does: `if (envPk)`). + +Run: `pnpm --filter @polygonlabs/agent-cli test` +Expected: FAIL (`DEFAULT_SEQUENCE_PUBLISHABLE_KEY` not exported; null return). + +- [ ] **Step 2: Implement** + +In `storage.ts`, above `loadOmsConfig`: + +```ts +// Default OMS publishable key so `wallet login` works with zero setup. +// Publishable keys are client-embeddable by design; users are wallets inside +// the CLI's shared OMS project. Currently the sandbox project key; swap to the +// production project key at the staging-to-production cutover. Override with +// SEQUENCE_PUBLISHABLE_KEY or `setup --oms-publishable-key`. +export const DEFAULT_SEQUENCE_PUBLISHABLE_KEY = ''; +``` + +(The implementer substitutes the real value: `python3 -c "import json;print(json.load(open('$HOME/.polygon-agent/builder.json'))['publishableKey'])"`.) + +Change `loadOmsConfig` to return type `OmsConfig` and replace its final `return null` with: + +```ts + return { publishableKey: DEFAULT_SEQUENCE_PUBLISHABLE_KEY, omsProjectId: envProj }; +``` + +(keep the env and file branches exactly as they are). In `oms-client.ts`, `getOmsClient`: remove the `if (!cfg) throw new Error('OMS credentials not configured...')` block (the compiler will flag it as unreachable once the return type narrows; delete the block and the stale comment). + +- [ ] **Step 3: Verify and commit** + +Run: `pnpm --filter @polygonlabs/agent-cli test && pnpm -r run typecheck` +Expected: 12/12 tests pass, typecheck clean. + +```bash +git add packages/polygon-agent-cli/src/lib/storage.ts packages/polygon-agent-cli/src/lib/oms-client.ts packages/polygon-agent-cli/src/lib/oms-config.test.ts +git commit -m "feat(cli): default publishable key so wallet login needs no setup" +``` + +--- + +### Task 3: ensureBuilderAccessKey provisioning lib with tests + +**Files:** +- Create: `packages/polygon-agent-cli/src/lib/builder-provision.ts` +- Test: `packages/polygon-agent-cli/src/lib/builder-provision.test.ts` + +**Interfaces:** +- Consumes: `getAuthToken`/`createProject`/`getDefaultAccessKey` from Task 1's `lib/builder-api.ts`; `generateEthAuthProof` from `lib/ethauth.ts`; `loadBuilderConfig`/`saveBuilderConfig` from `lib/storage.ts` (existing: `saveBuilderConfig({ privateKey, eoaAddress, accessKey, projectId })` encrypts the key and merges into builder.json). +- Produces: `ensureBuilderAccessKey(walletAddress: string, deps: ProvisionDeps): Promise`, `makeDefaultProvisionDeps(): ProvisionDeps`. Task 4 calls both. + +- [ ] **Step 1: Write the failing tests** + +Create `packages/polygon-agent-cli/src/lib/builder-provision.test.ts`: + +```ts +import { describe, expect, it } from 'vitest'; + +import { ensureBuilderAccessKey, type ProvisionDeps } from './builder-provision.ts'; + +function makeFakes(overrides: Partial = {}) { + const saved: unknown[] = []; + const deps: ProvisionDeps = { + loadBuilderConfig: async () => null, + saveBuilderConfig: async (cfg) => { + saved.push(cfg); + }, + createEoa: () => ({ privateKey: '0xkey', address: '0xE0A0000000000000000000000000000000000001' }), + generateProof: async () => 'eth.proof', + getAuthToken: async () => 'jwt-1', + createProject: async (name) => ({ id: 4242, name }), + getDefaultAccessKey: async () => 'AQAAAA-access-key', + ...overrides + }; + return { deps, saved }; +} + +const WALLET = '0xc2F4cAfe89AE7e1bcB86dd3f141C0a3adCEB6C17'; + +describe('ensureBuilderAccessKey', () => { + it('provisions a project and saves the credentials', async () => { + const { deps, saved } = makeFakes(); + const result = await ensureBuilderAccessKey(WALLET, deps); + expect(result).toEqual({ provisioned: true }); + expect(saved).toEqual([ + { + privateKey: '0xkey', + eoaAddress: '0xE0A0000000000000000000000000000000000001', + accessKey: 'AQAAAA-access-key', + projectId: 4242 + } + ]); + }); + + it('derives the project name from the wallet address', async () => { + let projectName = ''; + const { deps } = makeFakes({ + createProject: async (name) => { + projectName = name; + return { id: 1, name }; + } + }); + await ensureBuilderAccessKey(WALLET, deps); + expect(projectName).toBe('polygon-agent-c2f4cafe'); + }); + + it('short-circuits when an access key already exists', async () => { + const { deps, saved } = makeFakes({ + loadBuilderConfig: async () => + ({ accessKey: 'existing', projectId: 1, privateKey: 'x', eoaAddress: '0x1' }) as never + }); + const result = await ensureBuilderAccessKey(WALLET, deps); + expect(result).toEqual({ provisioned: false, reason: 'existing' }); + expect(saved).toEqual([]); + }); + + it('reports the failing stage without throwing', async () => { + const { deps: authFail } = makeFakes({ + getAuthToken: async () => { + throw new Error('GetAuthToken failed: 500'); + } + }); + await expect(ensureBuilderAccessKey(WALLET, authFail)).resolves.toEqual({ + provisioned: false, + reason: 'auth: GetAuthToken failed: 500' + }); + + const { deps: projectFail, saved } = makeFakes({ + createProject: async () => { + throw new Error('CreateProject failed: 403'); + } + }); + await expect(ensureBuilderAccessKey(WALLET, projectFail)).resolves.toEqual({ + provisioned: false, + reason: 'project: CreateProject failed: 403' + }); + expect(saved).toEqual([]); + }); +}); +``` + +Run: `pnpm --filter @polygonlabs/agent-cli test` +Expected: FAIL, cannot resolve `./builder-provision.ts`. + +- [ ] **Step 2: Implement** + +Create `packages/polygon-agent-cli/src/lib/builder-provision.ts`: + +```ts +// Post-login Builder provisioning: gives every agent its own Sequence Builder +// project + access key (indexer and Trails quota) with zero manual steps. +// Signs an ETHAuth proof with an ephemeral EOA, exactly like `setup` always +// did, but runs automatically after `wallet login`. Best-effort by contract: +// this function never throws; a failure must never fail a completed login. + +import { ethers } from 'ethers'; + +import { getAuthToken, createProject, getDefaultAccessKey } from './builder-api.ts'; +import { generateEthAuthProof } from './ethauth.ts'; +import { loadBuilderConfig, saveBuilderConfig } from './storage.ts'; + +export interface ProvisionDeps { + loadBuilderConfig(): Promise<{ accessKey?: string } | null>; + saveBuilderConfig(cfg: { + privateKey: string; + eoaAddress: string; + accessKey: string; + projectId: number; + }): Promise; + createEoa(): { privateKey: string; address: string }; + generateProof(privateKey: string): Promise; + getAuthToken(proof: string): Promise; + createProject(name: string, jwt: string): Promise<{ id: number; name: string }>; + getDefaultAccessKey(projectId: number, jwt: string): Promise; +} + +export interface ProvisionResult { + provisioned: boolean; + reason?: string; +} + +export function makeDefaultProvisionDeps(): ProvisionDeps { + return { + loadBuilderConfig, + saveBuilderConfig, + createEoa: () => { + const wallet = ethers.Wallet.createRandom(); + return { privateKey: wallet.privateKey, address: wallet.address }; + }, + generateProof: (privateKey) => generateEthAuthProof(privateKey), + getAuthToken, + createProject, + getDefaultAccessKey + }; +} + +/** Provision a Builder project + access key unless one already exists. Never throws. */ +export async function ensureBuilderAccessKey( + walletAddress: string, + deps: ProvisionDeps +): Promise { + try { + const existing = await deps.loadBuilderConfig(); + if (existing?.accessKey) return { provisioned: false, reason: 'existing' }; + } catch { + // An unreadable config is treated as absent; provisioning may repair it. + } + + const eoa = deps.createEoa(); + + let jwt: string; + try { + const proof = await deps.generateProof(eoa.privateKey); + jwt = await deps.getAuthToken(proof); + } catch (error) { + return { provisioned: false, reason: `auth: ${(error as Error).message}` }; + } + + const projectName = `polygon-agent-${walletAddress.slice(2, 10).toLowerCase()}`; + + let projectId: number; + try { + const project = await deps.createProject(projectName, jwt); + projectId = project.id; + } catch (error) { + return { provisioned: false, reason: `project: ${(error as Error).message}` }; + } + + try { + const accessKey = await deps.getDefaultAccessKey(projectId, jwt); + await deps.saveBuilderConfig({ + privateKey: eoa.privateKey, + eoaAddress: eoa.address, + accessKey, + projectId + }); + return { provisioned: true }; + } catch (error) { + return { provisioned: false, reason: `access-key: ${(error as Error).message}` }; + } +} +``` + +- [ ] **Step 3: Verify and commit** + +Run: `pnpm --filter @polygonlabs/agent-cli test && pnpm --filter @polygonlabs/agent-cli typecheck` +Expected: 16/16 tests pass. + +```bash +git add packages/polygon-agent-cli/src/lib/builder-provision.ts packages/polygon-agent-cli/src/lib/builder-provision.test.ts +git commit -m "feat(cli): auto-provision Builder access key after login" +``` + +--- + +### Task 4: Wire provisioning into wallet login and update docs + +**Files:** +- Modify: `packages/polygon-agent-cli/src/commands/wallet.ts` (handleLogin) +- Modify: `packages/polygon-agent-cli/README.md`, `skills/SKILL.md`, `skills/polygon-agent-cli/SKILL.md`, `CLAUDE.md` (onboarding sections) + +**Interfaces:** +- Consumes: `ensureBuilderAccessKey`, `makeDefaultProvisionDeps` (Task 3). +- Produces: `wallet login` success JSON gains `builderProvisioned: boolean`; onboarding docs collapse to `wallet login`. + +- [ ] **Step 1: Wire into handleLogin** + +In `wallet.ts`, add the import: + +```ts +import { ensureBuilderAccessKey, makeDefaultProvisionDeps } from '../lib/builder-provision.ts'; +``` + +In `handleLogin`, between `await saveOmsWalletPointer(...)` and the `jsonOut(...)` success line, insert: + +```ts + // Zero-setup onboarding: give this agent its own Builder project + access + // key (indexer and Trails quota). Best-effort: a failure never fails the + // login and provisioning retries on the next login. + const provision = await ensureBuilderAccessKey(walletAddress, makeDefaultProvisionDeps()); + const builderProvisioned = provision.provisioned || provision.reason === 'existing'; + if (!builderProvisioned) { + process.stderr.write( + `Note: Builder provisioning failed (${provision.reason}). ` + + 'Indexer and Trails calls fall back to shared defaults; it will retry on the next login.\n' + ); + } +``` + +and change the success output to: + +```ts + jsonOut({ ok: true, walletName: argv.name, walletAddress, loginMethod, builderProvisioned }); +``` + +(The already-logged-in short-circuit near the top of `handleLogin` stays untouched: it does not provision, because no new login happened.) + +- [ ] **Step 2: Update docs** + +All four docs say the same thing in their own voice, no em dashes: +- Onboarding is one command: `polygon-agent wallet login`. No key setup is needed: the CLI ships a default publishable key, and after login it automatically creates a Sequence Builder project and saves the access key to `~/.polygon-agent/builder.json`. +- `setup --oms-publishable-key` and `SEQUENCE_PUBLISHABLE_KEY` remain as overrides for developers pointing at their own OMS project; plain `setup` remains for manual or `--force` re-provisioning. Mark both as advanced. +- In `skills/polygon-agent-cli/SKILL.md` and `skills/SKILL.md`, update the quickstart (remove the setup step), the env-var table (`SEQUENCE_PUBLISHABLE_KEY` becomes optional override), the onboarding note, and the troubleshooting row for `OMS credentials not configured` (that error no longer exists; remove the row). +- In `CLAUDE.md`, update the "Requires SEQUENCE_PUBLISHABLE_KEY" bullet to describe the default + override. +- In `README.md`, update the getting-started and env-var sections accordingly. + +- [ ] **Step 3: Smoke-check with a clean HOME** + +```bash +CLEAN=$(mktemp -d) +HOME="$CLEAN" SEQUENCE_PUBLISHABLE_KEY= timeout 20 pnpm exec tsx packages/polygon-agent-cli/src/index.ts wallet login --timeout 8 --no-fund; echo "exit=$?" +ls "$CLEAN/.polygon-agent" 2>/dev/null || echo "no storage dir" +``` + +Expected: with NO builder.json and NO env key, the command prints `Open this URL to sign in:` with an agentconnect login URL (proving the baked default key constructed the OMS client), then times out after ~8s with the timed-out JSON error. No `OMS credentials not configured` error anywhere. + +- [ ] **Step 4: Full verification and commit** + +Run: `pnpm --filter @polygonlabs/agent-cli test && pnpm -r run typecheck && pnpm --filter @polygonlabs/agent-cli lint` +Expected: 16/16, clean, clean. + +```bash +git add packages/polygon-agent-cli/src/commands/wallet.ts packages/polygon-agent-cli/README.md skills/SKILL.md skills/polygon-agent-cli/SKILL.md CLAUDE.md +git commit -m "feat(cli): wallet login auto-provisions Builder credentials (zero-setup onboarding)" +``` + +--- + +### Task 5: Live end-to-end on a clean profile + +**Files:** none (verification only; fixes found here get their own commits). + +- [ ] **Step 1: Real login with a fresh HOME (human in the loop)** + +```bash +CLEAN=$(mktemp -d) +HOME="$CLEAN" pnpm exec tsx packages/polygon-agent-cli/src/index.ts wallet login --no-fund +``` + +The human completes the browser login (Google or email). Expected JSON: `{"ok":true,...,"builderProvisioned":true}`. + +- [ ] **Step 2: Verify the provisioned state** + +```bash +python3 - < 12 else v) for k, v in d.items()}) +EOF +``` + +Expected keys: `privateKey` (encrypted blob), `eoaAddress`, `accessKey`, `projectId`. No `publishableKey` needed (default in code). + +- [ ] **Step 3: Prove the quota chain works with zero env vars** + +```bash +HOME="$CLEAN" pnpm exec tsx packages/polygon-agent-cli/src/index.ts balances +HOME="$CLEAN" pnpm exec tsx packages/polygon-agent-cli/src/index.ts deposit --asset USDC --amount 0.1 +``` + +Expected: `balances` returns (zero balances are fine; it proves the indexer accepts the provisioned access key); `deposit` dry-run resolves an earn pool via Trails using the same key. Clean up: remove the wallet via the page/`wallet remove` and delete `$CLEAN`. + +- [ ] **Step 4: Regression on the developer profile** + +On the normal HOME (existing builder.json with accessKey): `pnpm exec tsx packages/polygon-agent-cli/src/index.ts wallet login --name regress --force --no-fund`, complete login, expect `builderProvisioned: true` (reason existing, no new project created; confirm `projectId` in `~/.polygon-agent/builder.json` is unchanged). Remove the `regress` wallet after. diff --git a/docs/superpowers/plans/2026-07-16-oms-wallet-sdk-migration.md b/docs/superpowers/plans/2026-07-16-oms-wallet-sdk-migration.md new file mode 100644 index 0000000..dbfb14e --- /dev/null +++ b/docs/superpowers/plans/2026-07-16-oms-wallet-sdk-migration.md @@ -0,0 +1,237 @@ +# OMS Wallet SDK Migration Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax. + +**Goal:** Migrate the CLI from `@0xsequence/typescript-sdk@0.1.0-alpha.4` to `@polygonlabs/oms-wallet@0.2.0`, re-architecting the Google OIDC leg onto the SDK's OMS relay and simplifying our relay worker. + +**Architecture:** Mechanical rename swap for email/tx/indexer/errors/networks; a re-architected Google leg where the OMS relay owns the OAuth callback and returns the browser to an `omsRelayReturnUri` (the agentconnect `/login` page), which posts the callback URL back to the CLI over the existing `LoginSession` pairing channel; the CLI calls `completeOidcRedirectAuth({ callbackUrl })`. Our custom `OidcHandoff` DO and `/api/oidc/*` routes are deleted. Spec: `docs/superpowers/specs/2026-07-16-oms-wallet-sdk-migration-design.md`. + +**Tech Stack:** TypeScript, `@polygonlabs/oms-wallet@0.2.0` (viem ^2.48.4, Node 22+), Cloudflare Workers + Durable Objects, React 18 + Vite, vitest. + +## Global Constraints + +- Conventional commit messages, lowercase subject (commitlint `subject-case`: no Sentence/Title/UPPER case in the subject); package scope; never a Co-Authored-By trailer. +- Pre-commit hook runs `pnpm -r run typecheck` across all packages; lint-staged may reformat. +- No em dashes in any copy or comments; sentence case. +- Canonical skill docs live in the repo-root `skills/` tree only. +- `LoginAction`/`LoginStatus` shapes are duplicated verbatim across `packages/oidc-relay/src/login-session.ts`, `packages/polygon-agent-cli/src/lib/browser-login.ts`, and `packages/agentconnect-ui/src/login/machine.ts`; keep them in sync. +- New pinned dep: `@polygonlabs/oms-wallet@0.2.0`. Remove `@0xsequence/typescript-sdk`. Ensure CLI `viem` satisfies the SDK's `^2.48.4` (bump the CLI's `viem ^2.45.3` to `^2.48.4`). +- Do not adopt new SDK features beyond what the current code used (no signInWithOidcIdToken, callContract, BYO providers). + +## Symbol reference (used across tasks) + +New import module `@polygonlabs/oms-wallet`. Renames: `OMSClient`→`OMSWallet`, `isOmsSdkError`→`isOMSWalletError`. Unchanged names: `EthereumPrivateKeyCredentialSigner`, `findNetworkById`, `StorageManager`, `FeeOptionWithBalance`, `TransactionMode`, `TokenBalance`. OIDC: `OmsRelayOidcProviders` (`.google`), `StartOidcRedirectAuthParams` (`{ provider, omsRelayReturnUri? }`), `StartOidcRedirectAuthResult` (`{ authorizationUrl }`), `CompleteOidcRedirectAuthParams` (`{ callbackUrl?, walletSelection? }`). + +New `LoginAction` variant (all three copies): `{ type: 'oidc-callback'; callbackUrl: string }`. + +--- + +### Task 1: Dependency swap and mechanical renames (non-OIDC) + +**Files:** +- Modify: `packages/polygon-agent-cli/package.json` (deps, engines), root `.nvmrc` if needed, root `package.json` engines +- Modify: `packages/polygon-agent-cli/src/lib/oms-storage.ts`, `oms-tx.ts`, `indexer.ts`, `src/commands/operations.ts`, `src/commands/operations-ui.tsx` +- Modify: `packages/polygon-agent-cli/src/lib/oms-client.ts` (OMSClient→OMSWallet only; OIDC helper removal is Task 3) + +**Interfaces:** +- Produces: `getOmsClient()` returns an `OMSWallet`; all non-OIDC imports resolve from `@polygonlabs/oms-wallet`. Later tasks build on this compiling. + +- [ ] **Step 1: Swap the dependency** + +In `packages/polygon-agent-cli/package.json`: remove `"@0xsequence/typescript-sdk": "0.1.0-alpha.4"`, add `"@polygonlabs/oms-wallet": "0.2.0"`, bump `"viem"` to `"^2.48.4"`, and set `"engines": { "node": ">=22" }` (add the field if absent). Then run `pnpm install` and confirm the lockfile updates with no peer errors. + +- [ ] **Step 2: Rename imports in the mechanical sites** + +In each of `oms-storage.ts`, `oms-tx.ts`, `indexer.ts`, `operations.ts`, `operations-ui.tsx`: change the import specifier `@0xsequence/typescript-sdk` → `@polygonlabs/oms-wallet`. In `oms-tx.ts` also rename `isOmsSdkError` → `isOMSWalletError` at its import and call sites. In `oms-client.ts` change the import and `OMSClient` → `OMSWallet` in the import and the `new OMSClient(...)` construction (leave `oidcRelayRedirectUri` for Task 3). + +- [ ] **Step 3: Node version wording** + +`.nvmrc` is already Node 24 (dev); no change needed there. Update root `package.json` `engines.node` to `>=22` if it pins lower. (Doc wording updates land in Task 7.) + +- [ ] **Step 4: Verify and commit** + +Run: `pnpm --filter @polygonlabs/agent-cli typecheck` +Expected: the OIDC code in `wallet.ts`/`browser-login.ts` will still reference old shapes and MAY error; if so, this task's commit is allowed to leave those two files failing ONLY IF they are untouched here (they are). To keep the commit green, run typecheck and if `wallet.ts`/`browser-login.ts` are the only errors and they are about `startOidcRedirectAuth`/`state`, that is expected and fixed in Task 3-4. Prefer: land Task 1 + 3 + 4 before the pre-commit hook runs a full typecheck. Since the hook blocks a red commit, commit Tasks 1, 3, and 4 together if needed (the controller may merge these steps). Otherwise, if typecheck is green, commit: + +```bash +git add packages/polygon-agent-cli/package.json package.json pnpm-lock.yaml packages/polygon-agent-cli/src/lib/oms-storage.ts packages/polygon-agent-cli/src/lib/oms-tx.ts packages/polygon-agent-cli/src/lib/indexer.ts packages/polygon-agent-cli/src/commands/operations.ts packages/polygon-agent-cli/src/commands/operations-ui.tsx packages/polygon-agent-cli/src/lib/oms-client.ts +git commit -m "chore(cli): swap to @polygonlabs/oms-wallet and rename mechanical imports" +``` + +Note to controller: because the pre-commit hook runs a repo-wide typecheck, Tasks 1, 3, and 4 likely must be implemented and committed as one unit (the SDK swap makes the old OIDC calls in wallet.ts/browser-login.ts fail to typecheck until they are reworked). Dispatch them together, or have the implementer stage all three tasks' files and make one commit. Task 2 (relay), Task 5 (UI), Task 6 (docs/tests) are independently committable. + +--- + +### Task 2: Simplify the relay worker (delete OidcHandoff, add oidc-callback action) + +**Files:** +- Modify: `packages/oidc-relay/src/relay.ts` (remove OidcHandoff DO + `/api/oidc/*` routes; keep `/api/login/*`) +- Delete: `packages/oidc-relay/src/return-to.ts`, `packages/oidc-relay/src/return-to.test.ts` +- Modify: `packages/oidc-relay/src/login-session.ts` (`LoginAction` gains `oidc-callback`; `validAction` in relay.ts accepts it) +- Modify: `packages/oidc-relay/wrangler.toml` (drop OidcHandoff binding; add `deleted_classes` migration, all envs) + +**Interfaces:** +- Consumes: nothing new. +- Produces: relay serves only `/api/login/*`; `LoginAction` includes `{ type: 'oidc-callback'; callbackUrl: string }`. Tasks 3 and 5 rely on this action shape. + +- [ ] **Step 1: Extend the action type and validator** + +In `login-session.ts`, add to `LoginAction`: `| { type: 'oidc-callback'; callbackUrl: string }`. In `relay.ts` `validAction`, accept `type === 'oidc-callback'` when `callbackUrl` is a string, 1..2048 chars, starting `https://` or `http://localhost` / `http://127.0.0.1`. + +- [ ] **Step 2: Remove the OidcHandoff DO and /api/oidc routes** + +Delete the `OidcHandoff` class, the `DONE_HTML`/`FAIL_HTML`/`CLOSE_HTML` constants, the `validState`/`validReturnTo` usage tied to it, the `import { validReturnTo }`, and the three `/api/oidc/register|cb|poll` route blocks. Remove `OIDC_RELAY` from the `Env` interface and its `export { OidcHandoff }`. Keep everything under `/api/login/*` and the `LoginSession` export. Delete `return-to.ts` and `return-to.test.ts`. + +- [ ] **Step 3: wrangler.toml migration** + +Remove the `OIDC_RELAY` durable-object binding blocks (top-level, staging, production). Add a new migration tag (e.g. `v3`) with `deleted_classes = ["OidcHandoff"]` to each env's migration list. Keep the `LOGIN_SESSION` binding. + +- [ ] **Step 4: Verify and commit** + +Run: `pnpm --filter @polygonlabs/oidc-relay typecheck && pnpm --filter @polygonlabs/oidc-relay test` +Then a `wrangler dev` smoke on `/api/login/register` + `/api/login/action` with an `oidc-callback` action (expect 204) and confirm `/api/oidc/cb` now 404s. Commit: + +```bash +git add packages/oidc-relay/src/relay.ts packages/oidc-relay/src/login-session.ts packages/oidc-relay/wrangler.toml +git rm packages/oidc-relay/src/return-to.ts packages/oidc-relay/src/return-to.test.ts +git commit -m "refactor(oidc-relay): drop oidchandoff, keep login pairing, add oidc-callback action" +``` + +--- + +### Task 3: CLI OIDC client rework (oms-client + oidc-relay-client) + +**Files:** +- Modify: `packages/polygon-agent-cli/src/lib/oms-client.ts` (remove `oidcRelayRedirectUri`; keep relay/login base URL helpers) +- Modify: `packages/polygon-agent-cli/src/lib/oidc-relay-client.ts` (remove `registerRelaySession`/`pollRelayForCallback`; keep nothing OIDC-specific, or delete the file if now empty) +- Modify: `packages/polygon-agent-cli/src/lib/login-relay-client.ts` (drop `registerOidcHandoff`/`pollOidcCallback` from the relay dep; the callback now arrives as an `oidc-callback` action) + +**Interfaces:** +- Consumes: `LoginAction` with `oidc-callback` (Task 2). +- Produces: `BrowserLoginDeps['relay']` no longer has `registerOidcHandoff`/`pollOidcCallback`; `makeLoginRelay` returns only `registerSession`/`nextAction`/`setStatus`. Task 4 uses the trimmed shape. + +- [ ] **Step 1: oms-client.ts** + +Remove `oidcRelayRedirectUri()` and the `SEQUENCE_OIDC_RELAY_URI` reference (no `relayRedirectUri` in the new SDK). Keep `oidcRelayBaseUrl()` and `loginUiBaseUrl()` (still used for the pairing relay and the login page). `getOmsClient` already returns `OMSWallet` after Task 1. + +- [ ] **Step 2: Trim the relay clients** + +In `oidc-relay-client.ts`, remove `registerRelaySession` and `pollRelayForCallback`. If the file has no remaining exports, delete it and drop its imports. In `login-relay-client.ts`, remove `registerOidcHandoff` and `pollOidcCallback` from the returned object and the `import` of the deleted functions; keep `registerSession`, `nextAction`, `setStatus`. + +- [ ] **Step 3: Verify (compiles with Task 4)** + +Typecheck will fail until Task 4 rewrites the consumers in `browser-login.ts`/`wallet.ts`; implement Task 4 before committing (see Task 1 controller note). No standalone commit. + +--- + +### Task 4: CLI browser-login loop and wallet login rework + +**Files:** +- Modify: `packages/polygon-agent-cli/src/lib/browser-login.ts` (google branch + deps shape) +- Modify: `packages/polygon-agent-cli/src/lib/browser-login.test.ts` +- Modify: `packages/polygon-agent-cli/src/commands/wallet.ts` (handleLogin google + `--local`) + +**Interfaces:** +- Consumes: trimmed relay deps (Task 3); `OmsRelayOidcProviders`, new `startOidcRedirectAuth`/`completeOidcRedirectAuth` signatures. +- Produces: the migrated login flow. + +- [ ] **Step 1: Rework `runBrowserLogin`'s wallet dep and google branch** + +Update `BrowserLoginDeps['wallet']` OIDC methods to the new shapes: `startOidcRedirectAuth(p: { provider: unknown; omsRelayReturnUri: string }): Promise<{ authorizationUrl: string }>` and `completeOidcRedirectAuth(p: { callbackUrl: string; walletSelection: 'automatic' }): Promise<{ walletAddress: string }>`. Add `oidcProviderGoogle` to deps (the `OmsRelayOidcProviders.google` value, injected so tests can fake it). Remove `registerOidcHandoff`/`pollOidcCallback` from `BrowserLoginDeps['relay']`. + +Rewrite the google branch: on the `google` action, call `startOidcRedirectAuth({ provider: deps.oidcProviderGoogle, omsRelayReturnUri: })`, publish `{ status: 'auth-url', url: authorizationUrl }`, then continue the action loop waiting for an `oidc-callback` action; on receiving it, call `completeOidcRedirectAuth({ callbackUrl, walletSelection: 'automatic' })`, publish `done`, return `{ walletAddress, loginMethod: 'google' }`. Keep the single error funnel and timeout. The `omsRelayReturnUri` is `${opts.uiBase}/login?s=${session}` (session in a query param so it survives the relay round-trip; the page reads `s`). + +- [ ] **Step 2: Update tests** + +Rewrite the google-flow tests in `browser-login.test.ts` to the new sequence (action `google` → status `auth-url` → action `{type:'oidc-callback', callbackUrl}` → `completeOidcRedirectAuth` → status `done`), with a fake `oidcProviderGoogle` sentinel and a fake wallet whose `startOidcRedirectAuth` returns `{ authorizationUrl }`. Keep email, cancel, timeout, relay-failure tests (email path unchanged). Add a test that a provider-start failure funnels an error status. + +- [ ] **Step 3: wallet.ts handleLogin** + +In the browser branch, build deps with `oidcProviderGoogle: OmsRelayOidcProviders.google` (import from `@polygonlabs/oms-wallet`) and the trimmed relay. Remove `seqRelay`/`oidcRelayRedirectUri`. For `--local`: set `omsRelayReturnUri` to the loopback server URL, open `authorizationUrl`, capture the returned URL at the loopback server, and call `completeOidcRedirectAuth({ callbackUrl, walletSelection: 'automatic' })`. If the loopback rework is blocked by relay return-URI constraints, make `--local` print that Google-over-local is unavailable and to use the default flow, and keep `--local` for nothing else (decide in Task 8 e2e). Keep the already-logged-in short-circuit and Builder provisioning. + +- [ ] **Step 4: Verify and commit (with Tasks 1 and 3)** + +Run: `pnpm --filter @polygonlabs/agent-cli test && pnpm -r run typecheck` +Commit Tasks 1, 3, 4 together (see Task 1 note): + +```bash +git add packages/polygon-agent-cli +git commit -m "feat(cli): migrate google login to the oms-wallet relay redirect flow" +``` + +--- + +### Task 5: agentconnect-ui login page rework + +**Files:** +- Modify: `packages/agentconnect-ui/src/login/machine.ts`, `machine.test.ts` +- Modify: `packages/agentconnect-ui/src/login/LoginPage.tsx` + +**Interfaces:** +- Consumes: the pairing `/api/login` routes and the `oidc-callback` action. +- Produces: the page that redirects to `authorizationUrl` and, on return from the OMS relay, posts the callback URL back. + +- [ ] **Step 1: machine.ts** + +Add `LoginAction` `oidc-callback` to the UI copy for type parity. The status/state machine is mostly unchanged (`auth-url` still triggers the redirect side effect; `done`/`error`/`expired` terminal). Add a state or flag for "returned from relay, posting callback" if helpful (e.g. reuse `auth-pending`). Update tests for any new transition. + +- [ ] **Step 2: LoginPage.tsx** + +Read the session id from `?s=` (query) first, falling back to the `#` fragment for backward compatibility. On initial load, detect whether the URL carries the OMS relay callback params (the page was returned to from the relay). If so, POST `{ type: 'oidc-callback', callbackUrl: window.location.href }` to `/api/login/action` for this session, and show the "finishing sign in" state. Otherwise render the method chooser as today. Keep the `google-wait` → redirect-to-`authorizationUrl` side effect (the `auth-url` status carries the URL). Keep email/OTP unchanged. Keep the success auto-redirect to the dashboard. + +- [ ] **Step 3: Verify and commit** + +Run: `pnpm --filter @polygonlabs/agentconnect-ui typecheck && pnpm --filter @polygonlabs/agentconnect-ui lint && pnpm --filter @polygonlabs/agentconnect-ui test` +Commit: + +```bash +git add packages/agentconnect-ui/src/login +git commit -m "feat(agentconnect-ui): post oms relay callback back over the login pairing channel" +``` + +--- + +### Task 6: Docs, changeset, and Node-version wording + +**Files:** +- Modify: `CLAUDE.md`, `packages/polygon-agent-cli/README.md`, `skills/SKILL.md`, `skills/polygon-agent-cli/SKILL.md` +- Modify/Create: `.changeset/*.md` + +**Interfaces:** none. + +- [ ] **Step 1: Docs** + +Update any "Node 20+" to "Node 22+". Update the wallet-auth description if it mentions `SEQUENCE_OIDC_RELAY_URI` or our `/api/oidc/cb` capture (now the OMS relay handles the Google callback). Do not rename the storage dir or env vars unrelated to this change. + +- [ ] **Step 2: Changeset** + +Add `.changeset/oms-wallet-sdk.md` (`"@polygonlabs/agent-cli": minor`): migrates the embedded wallet to `@polygonlabs/oms-wallet`, requires Node 22+, and re-architects the Google login onto the OMS relay (no behavior change for users beyond the Node floor). Lowercase-subject-safe body; no em dashes. + +- [ ] **Step 3: Commit** + +```bash +git add CLAUDE.md packages/polygon-agent-cli/README.md skills/SKILL.md skills/polygon-agent-cli/SKILL.md .changeset +git commit -m "docs: note oms-wallet migration and node 22 requirement" +``` + +--- + +### Task 7: Build, unit-verify, and live e2e + +**Files:** none (verification; fixes get their own commits). + +- [ ] **Step 1: Full build + unit** + +`pnpm -r run typecheck`, `pnpm -r --if-present run test`, `pnpm --filter @polygonlabs/agent-cli run build`. All green. + +- [ ] **Step 2: Deploy the relay + UI to staging** + +Deploy `oidc-relay` staging (confirm the `deleted_classes` migration applies cleanly and `/api/login` still serves; `/api/oidc/cb` 404s) and agentconnect-ui staging (with the new LoginPage). Note: the OMS relay must allow the `omsRelayReturnUri` (`agentconnect.staging.polygon.technology/login`); confirm with the embedded-wallet team that the return URI is allowlisted, since the target changed from `/api/oidc/cb`. + +- [ ] **Step 3: Live e2e (human in the loop)** + +From a clean HOME, `agent wallet login`: real Google login through the OMS relay leg, confirm the page returns and posts the callback, the CLI completes and reports `builderProvisioned` and a wallet address; email login (regression); a `--local` attempt (record whether Google-over-local works or is disabled). Then `agent balances` and `agent deposit --asset USDC --amount 0.1` dry-run to confirm indexer + Trails via the migrated SDK. Resolve the session-carry / callback-param known unknown here; if `?s=` does not survive, switch to a path-encoded session and re-verify. + +- [ ] **Step 4: Whole-branch review, then re-cut the release** + +Run the final whole-branch review. Once green, re-cut the held release (PR #126 equivalent) on top of this branch so production ships on the new SDK, and update the production checklist (allowlist target is now the `omsRelayReturnUri`, not `/api/oidc/cb`). diff --git a/docs/superpowers/specs/2026-07-13-browser-login-design.md b/docs/superpowers/specs/2026-07-13-browser-login-design.md new file mode 100644 index 0000000..383260c --- /dev/null +++ b/docs/superpowers/specs/2026-07-13-browser-login-design.md @@ -0,0 +1,113 @@ +# Browser login via agentconnect-ui + +Date: 2026-07-13 +Status: approved + +## Problem + +`polygon-agent wallet login` prints a raw Google sign-in URL. There is no branding, no method choice, and the local/remote split leaks into the UX (`--remote` plus a relay URL for headless hosts). The Sequence SDK supports email OTP auth, but the CLI never wired it up. + +## Decision summary + +- A branded login page on agentconnect-ui becomes the default `wallet login` experience for all logins, local and remote alike. +- The user picks Google or email on the page. Email OTP entry happens on the page, not in the terminal. +- After a successful login the page shows a success state that points the user to wallet.polygon.technology. +- Architecture is device-flow pairing (approach A): the CLI keeps all key material and drives the SDK auth locally; the page is only an input surface; the relay carries a short-lived two-way session. + +Rejected alternatives: a thin wrapper page (cannot do email on the page) and browser-owned auth with session handoff (would move credential material through the relay, and the SDK does not support re-binding a session to another signer). + +## Architecture + +Three components, all existing packages: + +1. `packages/oidc-relay`: gains a second Durable Object class, `LoginSession`, alongside the untouched `OidcHandoff`. Carries the pairing session between browser and CLI. +2. `packages/agentconnect-ui`: gains a `/login` SPA route. Session id arrives in the URL fragment so it never reaches server logs. +3. `packages/polygon-agent-cli`: `handleLogin` becomes an action loop that polls the relay for user input and drives the SDK locally. + +The PKCE verifier, the credential signer key, and the wallet session never leave the CLI process. This matches the existing `--remote` security model. + +## Relay protocol + +New routes under `/api/login`, backed by the `LoginSession` DO (one instance per session id). Session ids are CLI-generated, 128-bit crypto-random, base64url. Validation mirrors the existing `validState` guard. TTL is 10 minutes via the alarm, same as `OidcHandoff`. + +| Route | Caller | Purpose | +|---|---|---| +| `POST /api/login/register {session}` | CLI | Arm a session | +| `POST /api/login/action {session, action}` | Browser | Send user input | +| `GET /api/login/next-action?session=` | CLI | Poll for the oldest unconsumed action (one-time read per action) | +| `POST /api/login/status {session, status, ...}` | CLI | Publish current state | +| `GET /api/login/status?session=` | Browser | Poll state (repeat-readable, survives page refresh) | + +Actions: `{type:'google'}`, `{type:'email', email}`, `{type:'otp', code}`, `{type:'cancel'}`. + +Statuses: `awaiting-method`, `auth-url` (+url), `otp-sent`, `otp-invalid` (+attemptsLeft), `done` (+walletAddress), `error` (+message). + +One-time action reads prevent OTP replay. The final `done` or `error` status stays readable until TTL so a refreshed page still resolves. + +### OidcHandoff change + +`POST /api/oidc/register` accepts an optional `returnTo` URL. After capturing `code`+`state`, the callback 302s the browser to `returnTo` (the branded login page) instead of serving the bare `DONE_HTML`. When `returnTo` is absent, behavior is unchanged, which keeps the `--local` fallback and any old CLI versions working. `returnTo` is validated as an https URL on an allowlisted host (the agentconnect UI domains) before being stored. + +The Sequence-allowlisted redirect URI (`/api/oidc/cb`) is untouched, so no Google client or Sequence relay change is needed. + +## Flows + +### Google + +1. CLI registers session S, prints and opens `https://agentconnect.polygon.technology/login#S`. +2. Page polls status (`awaiting-method`), user clicks Continue with Google, page posts `{type:'google'}`. +3. CLI sees the action, calls `startOidcRedirectAuth` pointed at the relay `/api/oidc/cb`, registers the OidcHandoff with `returnTo = login#S`, publishes `auth-url`. +4. Page redirects to the auth URL. Google, then the Sequence relay, then our relay callback captures code+state and 302s back to the login page. +5. CLI polls the existing `/api/oidc/poll`, calls `completeOidcRedirectAuth`, saves the wallet pointer (`loginMethod: 'google'`), publishes `done` with the wallet address. +6. Page shows success and links to wallet.polygon.technology. + +### Email + +1. Same session setup. User enters their email address, page posts `{type:'email', email}`. +2. CLI calls `startEmailAuth({email})`, publishes `otp-sent`. +3. Page shows the code input. User types the code from their inbox, page posts `{type:'otp', code}`. +4. CLI calls `completeEmailAuth({code})`. Bad code: publish `otp-invalid` with attempts remaining, page re-prompts. Success: save pointer (`loginMethod: 'email'`), publish `done`. + +## CLI changes + +- `wallet login` defaults to the browser flow. It requires a relay and UI base URL; production values ship as baked-in defaults, overridable via `POLYGON_AGENT_OIDC_RELAY` (existing) and a new `POLYGON_AGENT_LOGIN_UI`. +- `--local` preserves today's loopback flow (raw Google URL, localhost callback). It is also the suggested remedy when session registration fails because the relay is unreachable; the CLI fails fast with that hint rather than auto-falling back. +- `--remote` becomes a deprecated no-op with a notice, since the default flow already works remotely. `--relay-url` still overrides the relay. +- `--provider` only applies to `--local`; in the browser flow the method choice lives on the page. +- Post-login funding: the CLI no longer auto-opens the funding URL when login came through the page (the success page directs the user onward). It still prints the funding panel; `--no-fund` still suppresses it. The `--local` path keeps today's behavior. +- The action loop is factored into a function that takes a relay client and an OMS client so it can be unit-tested with fakes. + +## Security notes + +- Key material: PKCE verifier and credential signer key stay in the CLI process, unchanged from today. +- The email address and the OTP transit the relay over TLS, are one-time read, live at most 10 minutes, and are useless without the CLI's in-flight SDK auth attempt. +- Session id is unguessable (128-bit) and carried in the URL fragment. +- `returnTo` is host-allowlisted to prevent open-redirect abuse of the callback. +- Sessions are purged on completion; actions cannot be replayed. + +## Error handling + +- Session TTL expiry: CLI times out with the same message shape as today; the page shows a link-expired state telling the user to re-run `polygon-agent wallet login`. +- Provider errors at Google flow through the existing error capture, surface as CLI errors, and are published as `status: error` for the page. +- OTP retry: bounded by the SDK's attempt limit. `attemptsLeft` is optional in the `otp-invalid` status; the page shows it when the SDK reports it, and shows a terminal error state once attempts are exhausted. +- Cancel on the page ends the CLI command with a non-zero exit and a clear message. + +## Deploy prerequisites + +- Enable the relay's production custom domain (currently commented out in `packages/oidc-relay/wrangler.toml`) and have Sequence allowlist its `/api/oidc/cb` as a redirect target (same allowlist add as was done for staging). +- Deploy the `/login` route to agentconnect staging and production. +- Ship the CLI with the production relay and UI URLs as defaults. + +## Testing + +- Relay: handler-level tests for the `LoginSession` DO (register, action queue one-time reads, status repeat reads, TTL purge, invalid session ids), mirroring how `OidcHandoff` is covered. +- CLI: unit tests of the action loop with fake relay and OMS clients (google happy path, email happy path, bad OTP retry, cancel, timeout, relay unreachable). +- UI: component-level tests of the login state machine (method choice, OTP retry, expired, error, success). +- End to end: manual run against agentconnect.staging.polygon.technology and the staging relay before flipping the CLI default. + +## Out of scope + +- Deleting the legacy loopback path (kept as `--local`). +- Any change to wallet.polygon.technology itself; the success page only links to it. +- Additional OIDC providers; the page offers Google and email only. +- Renaming the oidc-relay package, even though it now carries more than OIDC. diff --git a/docs/superpowers/specs/2026-07-14-zero-setup-onboarding-design.md b/docs/superpowers/specs/2026-07-14-zero-setup-onboarding-design.md new file mode 100644 index 0000000..2e9eb6e --- /dev/null +++ b/docs/superpowers/specs/2026-07-14-zero-setup-onboarding-design.md @@ -0,0 +1,40 @@ +# Zero-setup onboarding: default publishable key and automatic Builder provisioning + +Date: 2026-07-14 +Status: approved (design agreed in conversation) + +## Problem + +Onboarding today needs two manual steps before the wallet works: obtain an OMS publishable key and run `setup --oms-publishable-key` (or export `SEQUENCE_PUBLISHABLE_KEY`), and separately run `setup` to provision a Sequence Builder project and access key (which carries the indexer and Trails quota). The target is that `polygon-agent wallet login` is the entire onboarding. + +## Decision summary + +1. The CLI ships a baked-in default publishable key. Publishable keys are client-embeddable by design; the CLI is the app, users are wallets within its OMS project. The default is the current sandbox key (`pk_sdbx_01kqfw9z...`); swapping it to a production project key is added to the existing staging-to-production cutover checklist. Resolution order becomes: `SEQUENCE_PUBLISHABLE_KEY` env, then `builder.json`, then the baked default. `setup --oms-publishable-key` and the env var remain as overrides. +2. After a successful `wallet login` (browser and `--local` paths alike), the CLI auto-provisions Builder credentials when `builder.json` has no access key: generate an ephemeral EOA, sign an ETHAuth proof (existing `lib/ethauth.ts`), exchange it at `api.sequence.build` for a JWT, create a project, fetch the default access key, and save everything to `builder.json`. This is the code path `setup` already uses, relocated to run automatically. +3. Provisioning is best-effort and idempotent: it never fails the login (a warning goes to stderr and the login JSON reports `builderProvisioned: false`), and it is skipped when an access key already exists. It re-runs on the next login after a failure. +4. Rejected for now: signing the ETHAuth proof with the embedded smart wallet (which would bind the Builder project to the user identity and allow cross-machine recovery). A spike on 2026-07-14 showed the OMS SDK's `signTypedData` cannot sign the chainless ETHAuth domain, and Builder-side ERC-1271 verification for a counterfactual wallet is unverified. Revisit when the SDK or Builder surface changes. + +## Architecture + +- `packages/polygon-agent-cli/src/lib/storage.ts`: `loadOmsConfig()` returns the baked default instead of null when neither env nor `builder.json` provide a key. The "OMS credentials not configured" error path disappears. +- New `packages/polygon-agent-cli/src/lib/builder-provision.ts`: `ensureBuilderAccessKey(deps): Promise<{ provisioned: boolean; reason?: string }>` with injected deps (config load/save, proof generation, HTTP calls) so it is unit-testable with fakes. The Builder HTTP helpers move out of `setup-ui` into a shared module or are imported from it. +- `wallet.ts` `handleLogin`: after `saveOmsWalletPointer`, call `ensureBuilderAccessKey` best-effort; add `builderProvisioned` to the success JSON; print a one-line stderr note when provisioning fails. +- `setup` stays for overrides and re-provisioning (`--force`), documented as advanced. +- Project naming: `polygon-agent-` so a human can correlate a Builder project with an agent wallet. + +## Error handling + +- Any provisioning failure (network, Builder API error) is caught, reported on stderr with the failing stage, and surfaced as `builderProvisioned: false`. Login output is otherwise unchanged. +- A pre-existing `builder.json` access key short-circuits provisioning (`provisioned: false, reason: 'existing'`), preserving current users' projects. + +## Testing + +- Unit tests for `ensureBuilderAccessKey` with fake deps: fresh provisioning happy path, existing-key short-circuit, failure at each HTTP stage (login still succeeds), saved-config shape. +- `loadOmsConfig` default fallback covered by a test (env wins, file wins, default last). +- Manual verification: on a machine/profile with no `~/.polygon-agent`, `wallet login` alone yields a working wallet plus `builder.json` with publishableKey (default), accessKey, projectId; `balances` (indexer) and `deposit` dry-run (Trails) work with no env vars. + +## Out of scope + +- Wallet-signed Builder auth and cross-machine project recovery (follow-up). +- Any change to the OMS project the default key points at; swapping sandbox to production is a checklist item, not code. +- Deduplicating Builder projects across machines (each machine that provisions gets its own project, as `setup` does today). diff --git a/docs/superpowers/specs/2026-07-16-oms-wallet-sdk-migration-design.md b/docs/superpowers/specs/2026-07-16-oms-wallet-sdk-migration-design.md new file mode 100644 index 0000000..6fcd691 --- /dev/null +++ b/docs/superpowers/specs/2026-07-16-oms-wallet-sdk-migration-design.md @@ -0,0 +1,86 @@ +# Migrate to @polygonlabs/oms-wallet SDK + +Date: 2026-07-16 +Status: approved (scoped design agreed in conversation) + +## Problem + +The CLI depends on `@0xsequence/typescript-sdk@0.1.0-alpha.4` for the embedded wallet. Polygon now ships the same SDK, rebranded and updated, as `@polygonlabs/oms-wallet` (latest 0.2.0). We migrate to it. Most of the surface is a mechanical rename, but the OIDC redirect API was redesigned and intersects the browser-login flow, so that leg is re-architected. + +## Package facts + +- New package: `@polygonlabs/oms-wallet@0.2.0`, single dependency `viem ^2.48.4`, `engines.node >= 22`. +- Same internal shape as the old SDK; the main class is renamed `OMSClient` → `OMSWallet` with an identical constructor (`{ publishableKey, storage?, redirectAuthStorage?, credentialSigner? }`) and the same `.wallet` (OMSWalletClient) and `.indexer` (OMSWalletIndexerClient) sub-clients. + +## Node version bump + +The published CLI moves from Node 20+ to **Node 22+**. Update `.nvmrc` (already 24 for dev), the CLI `package.json` `engines.node`, `CLAUDE.md`, and README/skills wording that says "Node 20+". + +## Mechanical changes (unchanged behavior) + +Swap the dependency and update imports across the six current import sites (`oms-client.ts`, `oms-storage.ts`, `oms-tx.ts`, `indexer.ts`, `operations.ts`, `operations-ui.tsx`): + +| Old symbol | New symbol | Notes | +|---|---|---| +| `OMSClient` | `OMSWallet` | same constructor params; `getOmsClient` return type follows | +| `isOmsSdkError` | `isOMSWalletError` | error helper rename (oms-tx.ts) | +| `EthereumPrivateKeyCredentialSigner` | same | | +| `findNetworkById` | same | | +| `StorageManager` (type) | same | our `FileStorageManager` still implements it | +| `FeeOptionWithBalance` (type) | same | | +| `TransactionMode` | same | | +| `TokenBalance` (type) | same | now from the indexer client module, still exported from root | + +Unchanged method signatures we rely on, verified against the 0.2.0 types: `wallet.walletAddress`, `wallet.startEmailAuth`, `wallet.completeEmailAuth`, `wallet.signTypedData`, `wallet.sendTransaction`, `wallet.signOut`, `indexer.getBalances`. Email login, transactions, and balances need only the import/rename changes. + +## The OIDC redirect re-architecture (Google leg) + +The old API `startOidcRedirectAuth({ provider: 'google', redirectUri, relayRedirectUri }) -> { url, state }` is replaced by `startOidcRedirectAuth({ provider: OmsRelayOidcProviders.google, omsRelayReturnUri }) -> { authorizationUrl }`. Gone: our own `redirectUri`, the `state` handle, and `relayRedirectUri`. The OMS relay now owns the Google OAuth callback and returns the browser to a caller-nominated `omsRelayReturnUri`. PKCE/state is held internally in the SDK's `redirectAuthStorage` (our `FileStorageManager`, in the CLI process). + +### New flow (CLI holds the SDK; browser is a surface; existing LoginSession pairing reused) + +1. CLI calls `startOidcRedirectAuth({ provider: OmsRelayOidcProviders.google, omsRelayReturnUri })` where `omsRelayReturnUri` is the agentconnect `/login` page carrying this pairing session id. Returns `{ authorizationUrl }`; PKCE/state persists in the CLI's redirect store. +2. CLI publishes status `auth-url` (with `authorizationUrl`) to the LoginSession; the page redirects the browser there. +3. Browser completes Google; the OMS relay handles the callback and returns the browser to `omsRelayReturnUri`, appending its callback params. +4. The returned page reads its full URL (`window.location.href`) and posts it back to the CLI as a new pairing action `{ type: 'oidc-callback', callbackUrl }`. +5. CLI receives the action and calls `completeOidcRedirectAuth({ callbackUrl, walletSelection: 'automatic' })` → `{ walletAddress }`, then publishes `done`. + +### What this deletes + +The OMS relay now performs the OAuth capture our custom relay used to. Remove from `packages/oidc-relay`: +- The `OidcHandoff` Durable Object and the `/api/oidc/register|cb|poll` routes. +- `src/return-to.ts` and its tests (the `returnTo` open-redirect guard existed only for our capture). +- The `OidcHandoff` DO binding in `wrangler.toml`, with a `deleted_classes` migration (all three envs). + +Keep the `LoginSession` DO and `/api/login/*` routes. They remain the browser-to-CLI pairing channel, now also carrying the `oidc-callback` action. + +Remove from the CLI: `oidcRelayRedirectUri()` / `SEQUENCE_OIDC_RELAY_URI` (no `relayRedirectUri` anymore); `registerRelaySession` / `pollRelayForCallback` in `oidc-relay-client.ts` (state-keyed handoff is obsolete). + +### Protocol additions + +`LoginAction` (duplicated in relay `login-session.ts`, CLI `browser-login.ts`, UI `machine.ts`) gains `{ type: 'oidc-callback'; callbackUrl: string }`. The relay's `validAction` accepts it with a bounded `callbackUrl` (string, https or http-localhost, ≤ 2048 chars). + +### `--local` + +The loopback flow can no longer pass a localhost `redirectUri`. Rework it to set `omsRelayReturnUri` to the localhost callback server URL, open `authorizationUrl`, capture the returned URL at the loopback server, and call `completeOidcRedirectAuth({ callbackUrl })`. This still requires the OMS relay to allow a localhost return URI (the same localhost callback was allowlisted previously). If that proves unavailable, `--local` supports email only and prints a clear message; decide during the e2e task. + +## Known unknown (resolve with a live e2e, not by guessing) + +Whether the OMS relay preserves our session identifier on `omsRelayReturnUri` and how it appends callback params (query vs fragment) is not documented in the package. Default design: carry the session id in the `omsRelayReturnUri` (query param `?s=`, since fragments may be consumed by the relay), have the page read it and post back the full href. The e2e task confirms both the session and the callback params arrive; if the relay rejects dynamic query on the return URI (exact-match allowlist), fall back to encoding the session in the path. + +## Testing + +- Unit: relay `LoginSession` action validation incl. `oidc-callback`; CLI browser-login loop google path (fakes: action `google` → publish `auth-url` → action `oidc-callback` → `completeOidcRedirectAuth` → `done`); UI machine transitions for the return-from-relay leg; email/tx/indexer suites stay green after the rename. +- Live e2e (staging relay + agentconnect): real Google login (the re-architected leg), email login (regression), and a `--local` attempt; then `balances` and a `deposit` dry-run to confirm indexer + Trails still work through the migrated SDK. + +## Deploy / sequencing + +- Migration lands on its own branch; the in-flight release PR (#126) is held and will be re-cut on top of this once verified, so production ships on the new SDK. +- Removing the `OidcHandoff` DO needs a `deleted_classes` migration; staging deploy first, confirm the worker deploys and `/api/login` still serves, then production. +- The Sequence/OMS allowlist target shifts from our `/api/oidc/cb` to the `omsRelayReturnUri` (the agentconnect `/login` page). Note this for the production checklist; it changes what the embedded-wallet team allowlists. + +## Out of scope + +- Adopting the new SDK's `signInWithOidcIdToken`, `callContract`, `revokeAccess`, or custom (BYO) OIDC providers. +- The Google consent-screen rebrand (separate Google Cloud + Sequence config task). +- Rewriting transaction/indexer logic beyond the import/rename swap. diff --git a/packages/agentconnect-ui/.env.example b/packages/agentconnect-ui/.env.example new file mode 100644 index 0000000..1b52167 --- /dev/null +++ b/packages/agentconnect-ui/.env.example @@ -0,0 +1,13 @@ +# Copy to .env and fill values. + +# Trails widget API key (Fund onramp widget). +VITE_TRAILS_API_KEY= + +# Sequence indexer access key — used to show the USD balance in the dashboard. +VITE_INDEXER_ACCESS_KEY= + +# Fallback used as the indexer access key if VITE_INDEXER_ACCESS_KEY is unset. +VITE_PROJECT_ACCESS_KEY= + +# oidc-relay base URL for the /login pairing session. +VITE_OIDC_RELAY_URL=https://oidc-relay.polygon.technology diff --git a/packages/connector-ui/.gitignore b/packages/agentconnect-ui/.gitignore similarity index 100% rename from packages/connector-ui/.gitignore rename to packages/agentconnect-ui/.gitignore diff --git a/packages/connector-ui/eslint.config.js b/packages/agentconnect-ui/eslint.config.js similarity index 100% rename from packages/connector-ui/eslint.config.js rename to packages/agentconnect-ui/eslint.config.js diff --git a/packages/connector-ui/index.html b/packages/agentconnect-ui/index.html similarity index 92% rename from packages/connector-ui/index.html rename to packages/agentconnect-ui/index.html index 29eac86..7128ddb 100644 --- a/packages/connector-ui/index.html +++ b/packages/agentconnect-ui/index.html @@ -10,7 +10,7 @@ href="https://fonts.googleapis.com/css2?family=Fustat:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" /> - Polygon Agent Kit - Wallet Connector + Polygon Agent — Wallet
diff --git a/packages/connector-ui/package.json b/packages/agentconnect-ui/package.json similarity index 54% rename from packages/connector-ui/package.json rename to packages/agentconnect-ui/package.json index 061357e..1e6d97a 100644 --- a/packages/connector-ui/package.json +++ b/packages/agentconnect-ui/package.json @@ -1,43 +1,40 @@ { - "name": "@polygonlabs/agent-connector-ui", + "name": "@polygonlabs/agentconnect-ui", "private": true, - "version": "1.6.16", + "version": "0.0.0", "type": "module", - "description": "Wallet connector UI for Polygon Agent Kit - creates secure encrypted wallet sessions", + "description": "Wallet funding + dashboard UI for Polygon Agent CLI (login happens in the CLI)", "repository": { "type": "git", "url": "https://github.com/0xPolygon/polygon-agent-cli", - "directory": "packages/connector-ui" + "directory": "packages/agentconnect-ui" }, "scripts": { "dev": "vite", "build": "tsc -b && vite build", "preview": "vite preview", - "lint": "eslint .", - "start": "serve dist -s -l ${PORT:-3000}", - "postinstall": "(cp -n .env.example .env) || echo already exists", "typecheck": "tsc --noEmit", - "clean": "rm -rf dist node_modules *.tsbuildinfo" + "lint": "eslint .", + "test": "vitest run", + "deploy:staging": "npx -y wrangler@4 deploy --env staging", + "deploy:production": "npx -y wrangler@4 deploy --env production" }, "dependencies": { "0xtrails": "^0.14.0", - "@0xsequence/dapp-client": "3.0.0-beta.16", "@0xsequence/wallet-primitives": "3.0.0-beta.16", - "@polygonlabs/agent-shared": "workspace:*", - "@tailwindcss/vite": "^4.1.18", "lucide-react": "^0.564.0", - "ox": "^0.11.3", "react": "^18.3.1", "react-dom": "^18.3.1", - "serve": "^14.2.4", "tailwindcss": "^4" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20260317.1", + "@cloudflare/workers-types": "^4", + "@tailwindcss/vite": "^4.1.18", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.1", + "typescript": "^5", "vite": "^5.4.0", - "wrangler": "^4.67.0" + "vitest": "^3.0.0" } } diff --git a/packages/connector-ui/public/polygon-logo-full.webp b/packages/agentconnect-ui/public/polygon-logo-full.webp similarity index 100% rename from packages/connector-ui/public/polygon-logo-full.webp rename to packages/agentconnect-ui/public/polygon-logo-full.webp diff --git a/packages/connector-ui/public/polygon-logo.png b/packages/agentconnect-ui/public/polygon-logo.png similarity index 100% rename from packages/connector-ui/public/polygon-logo.png rename to packages/agentconnect-ui/public/polygon-logo.png diff --git a/packages/connector-ui/public/polygon-logo.svg b/packages/agentconnect-ui/public/polygon-logo.svg similarity index 100% rename from packages/connector-ui/public/polygon-logo.svg rename to packages/agentconnect-ui/public/polygon-logo.svg diff --git a/packages/connector-ui/src/App.css b/packages/agentconnect-ui/src/App.css similarity index 100% rename from packages/connector-ui/src/App.css rename to packages/agentconnect-ui/src/App.css diff --git a/packages/agentconnect-ui/src/App.tsx b/packages/agentconnect-ui/src/App.tsx new file mode 100644 index 0000000..d40743d --- /dev/null +++ b/packages/agentconnect-ui/src/App.tsx @@ -0,0 +1,501 @@ +import './App.css'; + +import type { ElementType } from 'react'; + +import { + AlertCircle, + ArrowLeftRight, + Copy, + Cpu, + Database, + FileText, + Globe, + Inbox, + Newspaper, + Plus, + Search, + Send, + Server, + Sparkles, + Target, + TrendingUp +} from 'lucide-react'; +import { useEffect, useMemo, useState } from 'react'; + +import { FundingScreen } from './components/FundingScreen.js'; +import { fetchTotalUsdBalance } from './indexer'; +import { LoginPage } from './login/LoginPage.js'; + +const SKILL_URL = 'https://agentconnect.polygon.technology/SKILL.md'; +// x402 services catalog skill: Services/Search prompts point the agent here so it +// knows which service routes to call (not the agentconnect/CLI skill). +const AGENTIC_SERVICES_SKILL_URL = 'https://agentic-services.polygon.technology/SKILL.md'; + +const AGENTS: { + id: string; + label: string; + color: string; + terminalPrefix: string; + buildCommand: (display: string, skillUrl: string) => string; +}[] = [ + { + id: 'claude', + label: 'Claude', + color: '#D97706', + terminalPrefix: 'claude', + buildCommand: (display, skillUrl) => `claude "Read ${skillUrl} and ${display}"` + }, + { + id: 'codex', + label: 'Codex', + color: '#10A37F', + terminalPrefix: 'codex', + buildCommand: (display, skillUrl) => `codex "Read ${skillUrl} and ${display}"` + }, + { + id: 'openclaw', + label: 'Openclaw', + color: '#8B5CF6', + terminalPrefix: 'clawhub', + buildCommand: (display, skillUrl) => `npx clawhub@latest run "Read ${skillUrl} and ${display}"` + }, + { + id: 'hermes', + label: 'Hermes', + color: '#EC4899', + terminalPrefix: 'hermes', + buildCommand: (display, skillUrl) => `hermes "Read ${skillUrl} and ${display}"` + } +]; + +type UseCase = { label: string; display: string; icon: ElementType }; +const SECTIONS: { name: string; skillUrl: string; items: UseCase[] }[] = [ + { + name: 'DeFi & Polymarket', + skillUrl: SKILL_URL, + items: [ + { + label: 'Make a bet on Polymarket', + display: 'Make a bet on a Polymarket market. Get the latest market prices and outcomes.', + icon: Target + }, + { + label: 'Bridge assets cross-chain', + display: + 'Bridge some USDC from Polygon to Base using the cheapest available route. Confirm the arrival and report the final balance on both chains.', + icon: ArrowLeftRight + }, + { + label: 'Automate yield strategies', + display: + 'Deposit USDC into the highest-yield active lending vault on Polygon and report the APY and pool address. Then set up a daily cron job to automatically re-evaluate and deposit into the best vault each morning.', + icon: TrendingUp + } + ] + }, + { + name: 'Services', + skillUrl: AGENTIC_SERVICES_SKILL_URL, + items: [ + { + label: 'Query any chain', + display: + 'Use QuickNode RPC over x402 to query on-chain data across 60+ chains with no API key. Get the latest Polygon block number and an account balance.', + icon: Server + }, + { + label: 'Wallet & token analytics', + display: + "Use Allium over x402 to pull a wallet's balances, PnL, transaction history, and token prices across chains.", + icon: Database + }, + { + label: 'Give your agent an inbox', + display: + 'Create an email inbox for your agent with AgentMail over x402, then send, receive, and read messages.', + icon: Inbox + }, + { + label: 'Run LLM inference', + display: + 'Run inference over x402 with Meta Llama on NVIDIA NIM: Llama 3.3 70B for chat and Llama 3.2 90B Vision for images.', + icon: Cpu + }, + { + label: 'Send an email', + display: 'Send a transactional email programmatically via Resend over x402.', + icon: Send + } + ] + }, + { + name: 'Search', + skillUrl: AGENTIC_SERVICES_SKILL_URL, + items: [ + { + label: 'Scrape a webpage', + display: 'Scrape any webpage with Firecrawl over x402 and get clean, LLM-ready markdown.', + icon: FileText + }, + { + label: 'Google search', + display: 'Run a Google search via SearchAPI over x402 and get structured JSON results.', + icon: Search + }, + { + label: 'Cloud browser', + display: + 'Spin up a cloud browser session with Browserbase over x402 for web automation and agent browsing.', + icon: Globe + }, + { + label: 'AI web search', + display: + 'Run an AI-native web search with Exa over x402 to get contextually relevant sources and highlights.', + icon: Sparkles + }, + { + label: 'Top headlines', + display: 'Get top news headlines by country, category, or keyword via NewsAPI over x402.', + icon: Newspaper + } + ] + } +]; + +// Shared logo header used on every screen. +export function LogoBadge() { + return ( +
+ Polygon + + >_ agent + +
+ ); +} + +// ── Dashboard: balance header, use-case picker + terminal, learn-more cards ── +function Dashboard({ + walletAddress, + chainId, + initialFundOpen +}: { + walletAddress: string; + chainId: number; + initialFundOpen: boolean; +}) { + const [totalUsd, setTotalUsd] = useState(null); + const [selectedSection, setSelectedSection] = useState(0); + const [selectedUseCase, setSelectedUseCase] = useState(0); + const [selectedAgent, setSelectedAgent] = useState('claude'); + const [copied, setCopied] = useState(false); + const [addrCopied, setAddrCopied] = useState(false); + const [fundOpen, setFundOpen] = useState(initialFundOpen); + + const items = SECTIONS[selectedSection].items; + + useEffect(() => { + let active = true; + setTotalUsd(null); + fetchTotalUsdBalance(walletAddress, chainId) + .then((v) => { + if (active) setTotalUsd(v); + }) + .catch(() => { + if (active) setTotalUsd(null); + }); + return () => { + active = false; + }; + }, [walletAddress, chainId]); + + const shortAddr = `${walletAddress.slice(0, 6)}..${walletAddress.slice(-4)}`; + + return ( +
+ {/* Nav */} + + +
+ {/* Balance row */} +
+
+
+ {totalUsd === null ? ( + $0.00 + ) : ( + `$${totalUsd.toLocaleString('en-US', { + minimumFractionDigits: 2, + maximumFractionDigits: 2 + })}` + )} +
+
+
+ {walletAddress} +
+
+ +
+ + {/* Section header */} +
+

Use your wallet with agents

+
+ + {/* Section nav bar */} +
+ {SECTIONS.map((section, i) => ( + + ))} +
+ + {/* Use cases + terminal */} +
+ {/* Left: use cases */} +
+
+ {items.map((uc, i) => { + const Icon = uc.icon; + return ( + + ); + })} +
+
+ + {/* Right: terminal */} +
+
+               a.id === selectedAgent)?.color }}
+              >
+                {AGENTS.find((a) => a.id === selectedAgent)?.terminalPrefix}
+              
+              {' "'}
+              {items[selectedUseCase].display}"
+            
+
+ {/* Agent selector chips */} +
+ Run with + {AGENTS.map((agent) => ( + + ))} +
+ +
+
+
+ + {/* Learn more */} +

Learn more

+
+ {[ + { + title: 'Github', + desc: 'Browse the source code, open issues, and contribute to the Polygon Agent CLI.', + href: 'https://github.com/0xPolygon/polygon-agent-cli' + }, + { + title: 'Docs', + desc: 'Full CLI reference, quickstart guide, and architecture docs to get your agent onchain fast.', + href: 'https://docs.polygon.technology/payment-services/agentic-payments/polygon-agent-cli' + }, + { + title: 'Add your Service for Agents', + desc: 'List your API as an x402 service that agents can discover and pay for per call.', + href: 'https://agentic-services.polygon.technology/discover' + } + ].map((card) => ( + +
+ {card.title} + + + +
+

{card.desc}

+
+ ))} +
+ +
+ Powered by Polygon +
+
+ + {fundOpen && ( +
setFundOpen(false)} + > +
e.stopPropagation()}> + setFundOpen(false)} + /> +
+
+ )} +
+ ); +} + +// ── Centered notice shown when opened without a wallet param ── +function MissingWalletNotice() { + return ( +
+
+ +
+
+ +

+ Open this page from the polygon-agent CLI. +

+
+
+ ); +} + +// ── Main App ── +function App() { + const params = useMemo(() => new URLSearchParams(window.location.search), []); + const walletAddress = params.get('wallet') || ''; + const chainId = Number(params.get('chain') || '137'); + + if (window.location.pathname === '/login') { + return ; + } + + if (!walletAddress) { + return ; + } + + // `?view=fund` (the CLI's `fund` deep link) opens the dashboard with the + // funding widget already popped up, rather than a separate page. + return ( + + ); +} + +export { App }; diff --git a/packages/connector-ui/src/components/FundingScreen.tsx b/packages/agentconnect-ui/src/components/FundingScreen.tsx similarity index 100% rename from packages/connector-ui/src/components/FundingScreen.tsx rename to packages/agentconnect-ui/src/components/FundingScreen.tsx diff --git a/packages/agentconnect-ui/src/config.ts b/packages/agentconnect-ui/src/config.ts new file mode 100644 index 0000000..5b6d81b --- /dev/null +++ b/packages/agentconnect-ui/src/config.ts @@ -0,0 +1,10 @@ +// Configured via VITE_* secrets (per-environment values set in GitHub Environments). + +// Trails widget API key (used by the Fund onramp widget). +export const trailsApiKey = (import.meta.env.VITE_TRAILS_API_KEY as string | undefined) ?? ''; + +// oidc-relay base URL for the /login pairing session (per-environment GitHub +// variable). CI passes the var unconditionally, so an unset variable arrives +// as an empty string and must fall back to the production default too. +const rawRelayUrl = import.meta.env.VITE_OIDC_RELAY_URL as string | undefined; +export const oidcRelayUrl = rawRelayUrl ? rawRelayUrl : 'https://oidc-relay.polygon.technology'; diff --git a/packages/connector-ui/src/index.css b/packages/agentconnect-ui/src/index.css similarity index 100% rename from packages/connector-ui/src/index.css rename to packages/agentconnect-ui/src/index.css diff --git a/packages/connector-ui/src/indexer.ts b/packages/agentconnect-ui/src/indexer.ts similarity index 57% rename from packages/connector-ui/src/indexer.ts rename to packages/agentconnect-ui/src/indexer.ts index c8abe99..d845b87 100644 --- a/packages/connector-ui/src/indexer.ts +++ b/packages/agentconnect-ui/src/indexer.ts @@ -4,11 +4,6 @@ import { Network } from '@0xsequence/wallet-primitives'; // The polygon indexer is at polygon-indexer.sequence.app; other chains follow -indexer.sequence.app const DEFAULT_INDEXER_BASE = 'https://{chain}-indexer.sequence.app/rpc/Indexer'; -export type BalanceSummary = { - // Some indexer payloads nest balances per chain; we keep this loose. - [k: string]: any; -}; - function getIndexerAccessKey(): string | undefined { return ( (import.meta.env.VITE_INDEXER_ACCESS_KEY as string | undefined) || @@ -19,26 +14,6 @@ function getIndexerAccessKey(): string | undefined { ); } -export function resolveChainId(params: URLSearchParams): number { - const chainIdRaw = params.get('chainId'); - if (chainIdRaw) { - const n = Number(chainIdRaw); - if (!Number.isFinite(n) || n <= 0) throw new Error(`Invalid chainId=${chainIdRaw}`); - return n; - } - - const chainName = (params.get('chain') || 'polygon').toLowerCase(); - const net = Network.getNetworkFromName(chainName); - if (!net) throw new Error(`Unsupported chain name: ${chainName}`); - return net.chainId; -} - -export function resolveNetwork(chainId: number) { - const net = Network.getNetworkFromChainId(chainId); - if (!net) throw new Error(`Unsupported chainId: ${chainId}`); - return net; -} - /** Returns the chain slug used in the Sequence indexer hostname (e.g. "polygon", "mainnet"). */ function chainSlug(chainId: number): string { // Sequence indexer host uses the network name; look it up or fall back to numeric id. @@ -124,61 +99,3 @@ export async function fetchTotalUsdBalance(walletAddress: string, chainId = 137) return total; } - -export async function fetchBalancesAllChains( - walletAddress: string, - chainId = 137 -): Promise { - const accessKey = getIndexerAccessKey(); - if (!accessKey) throw new Error('Missing indexer access key (set VITE_INDEXER_ACCESS_KEY)'); - - const base = indexerBase(chainId); - const headers: Record = { - 'Content-Type': 'application/json', - 'X-Access-Key': accessKey - }; - - const res = await fetch(`${base}/GetTokenBalances`, { - method: 'POST', - headers, - body: JSON.stringify({ - accountAddress: walletAddress, - includeMetadata: true - }) - }); - - if (!res.ok) throw new Error(`Indexer error: ${res.status}`); - return res.json(); -} - -// Attempts to extract the per-chain entry from a multi-chain indexer response. -export function pickChainBalances(all: any, chainId: number): any { - if (!all) return null; - - // Observed shapes vary; try common ones. - const candidates = [ - all?.chains?.[String(chainId)], - all?.chains?.[chainId], - all?.byChainId?.[String(chainId)], - all?.byChainId?.[chainId], - all?.results?.[String(chainId)], - all?.results?.[chainId] - ]; - for (const c of candidates) { - if (c) return c; - } - - // Some APIs return an array of chain entries. - const arr = all?.chainBalances || all?.chains || all?.results; - if (Array.isArray(arr)) { - const hit = arr.find( - (x: any) => String(x?.chainId) === String(chainId) || String(x?.chainID) === String(chainId) - ); - if (hit) return hit; - } - - // Fallback: if response already is a single-chain summary, return it. - if (all?.balances || all?.nativeBalances) return all; - - return null; -} diff --git a/packages/agentconnect-ui/src/login/LoginPage.tsx b/packages/agentconnect-ui/src/login/LoginPage.tsx new file mode 100644 index 0000000..fe9141d --- /dev/null +++ b/packages/agentconnect-ui/src/login/LoginPage.tsx @@ -0,0 +1,442 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; + +import type { LoginAction, MachineEvent, MachineState, RelayStatus } from './machine.js'; + +import { LogoBadge } from '../App.js'; +import { oidcRelayUrl } from '../config'; +import { initialState, reduce } from './machine.js'; +import { getSessionId, isRelayReturn } from './returnUrl.js'; + +// Poll fast while waiting on the CLI (returning from the provider, checking a +// code) so the transition to the dashboard feels immediate; poll slower while +// waiting on the user, to keep idle load light. +const ACTIVE_POLL_MS = 600; +const IDLE_POLL_MS = 1200; +const ACTIVE_WAIT: MachineState['kind'][] = [ + 'google-wait', + 'auth-pending', + 'email-wait', + 'otp-wait' +]; + +// Post-login destination: the dashboard in this same app, wallet prefilled. +// Same-origin, so it tracks whichever environment served the login page. +function dashboardUrl(walletAddress: string): string { + return `/?wallet=${walletAddress}&chain=137`; +} + +// Optimistic ui transitions must only happen after the relay has acknowledged +// the action. Returns true only when the POST actually landed, so call sites +// can stay put and let the user retry when it did not. +async function postAction(session: string, action: LoginAction): Promise { + try { + const res = await fetch(`${oidcRelayUrl}/api/login/action`, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ session, action }) + }); + return res.ok || res.status === 204; + } catch { + return false; + } +} + +// A transient relay failure (network error or a 5xx) must not terminate the +// session, so it returns null and the polling effect just skips that tick. +// Only a 400 (an invalid session id, which never becomes valid) maps to the +// terminal expired state. +async function fetchStatus(session: string): Promise { + try { + const res = await fetch( + `${oidcRelayUrl}/api/login/status?session=${encodeURIComponent(session)}` + ); + if (res.ok) return (await res.json()) as RelayStatus; + if (res.status === 400) return { status: 'expired' }; + return null; + } catch { + return null; + } +} + +const TERMINAL: MachineState['kind'][] = ['success', 'expired', 'failed']; + +// The OMS relay return URI is now the bare, static `/login` (required to +// match its allowlist exactly), so it can no longer carry the pairing +// session as a query param. Instead, the session is stashed here before the +// redirect to Google and recovered from here on the bounce back, since a +// sessionStorage entry survives that round trip on the same origin. +const SESSION_STORE_KEY = 'oms_login_session'; + +export function LoginPage() { + const relayReturn = isRelayReturn(window.location.search); + // Resolve the session from the url first (fresh CLI announce, or the + // legacy `?s=` shape); fall back to whatever was stashed before the + // redirect to Google. Runs once per mount via the lazy state initializer, + // so the sessionStorage write on a fresh url load never thrashes. + const [session] = useState(() => { + const fromUrl = getSessionId(window.location.search, window.location.hash); + if (fromUrl) { + try { + window.sessionStorage.setItem(SESSION_STORE_KEY, fromUrl); + } catch { + // Best-effort: storage may be unavailable (private browsing, etc). + // This load still has the session; it just won't survive a redirect. + } + return fromUrl; + } + try { + return window.sessionStorage.getItem(SESSION_STORE_KEY) ?? ''; + } catch { + return ''; + } + }); + const [state, setState] = useState(() => + relayReturn ? reduce(initialState, { type: 'relay-return' }) : initialState + ); + const dispatch = useCallback((event: MachineEvent) => { + setState((s) => reduce(s, event)); + }, []); + const redirected = useRef(false); + const postedRelayCallback = useRef(false); + + // On return from the OMS relay, hand the full callback url back to the CLI + // over the pairing channel once; the CLI exchanges it for the wallet and + // publishes `done`, which the poll below picks up like any other status. + // A failed post (a network error, or a 410 for a session that already + // expired) must not leave the user stuck on the "finishing sign in" + // spinner until the ~10-minute poll timeout, so a false result dispatches + // the terminal failed state right away. If the session could not be + // recovered at all (sessionStorage empty, e.g. a different browser or a + // cleared session), there is nothing to post against, so it fails fast + // instead of posting an empty session to the relay. + useEffect(() => { + if (postedRelayCallback.current || !relayReturn) return; + postedRelayCallback.current = true; + if (!session) { + dispatch({ + type: 'status', + status: { + status: 'error', + message: 'Could not recover the login session. Re-run wallet login in your terminal.' + } + }); + return; + } + void postAction(session, { type: 'oidc-callback', callbackUrl: window.location.href }).then( + (ok) => { + if (ok) return; + dispatch({ + type: 'status', + status: { + status: 'error', + message: 'Could not reach the login relay. Re-run wallet login in your terminal.' + } + }); + } + ); + }, [session, relayReturn, dispatch]); + + // Once the session is established the user should land on their dashboard + // without another click; the success card shows briefly, then we move on. + useEffect(() => { + if (state.kind !== 'success') return; + const target = dashboardUrl(state.walletAddress); + const timer = setTimeout(() => window.location.assign(target), 1800); + return () => clearTimeout(timer); + }, [state]); + + // Poll the relay for CLI-published status; redirect once when the auth url + // arrives (a side effect the reducer deliberately does not model). + useEffect(() => { + if (!session || TERMINAL.includes(state.kind)) return; + const timer = setInterval( + () => { + void fetchStatus(session).then((status) => { + if (status === null) return; // transient failure; keep polling + if (status.status === 'auth-url' && !redirected.current && state.kind === 'google-wait') { + redirected.current = true; + window.location.assign(status.url); + return; + } + dispatch({ type: 'status', status }); + }); + }, + ACTIVE_WAIT.includes(state.kind) ? ACTIVE_POLL_MS : IDLE_POLL_MS + ); + return () => clearInterval(timer); + }, [session, state.kind, dispatch]); + + if (!session) { + return ( + +

No login session

+

+ Open this page from the polygon-agent CLI: run + + agent wallet login + + in your terminal. +

+
+ ); + } + + return {renderState(state, session, dispatch)}; +} + +function Shell({ children }: { children: React.ReactNode }) { + return ( +
+
+ +
+
+ {children} +
+
+ ); +} + +function renderState(state: MachineState, session: string, dispatch: (e: MachineEvent) => void) { + switch (state.kind) { + case 'method': + return ( + { + void postAction(session, { type: 'google' }).then((ok) => { + if (ok) dispatch({ type: 'choose-google' }); + }); + }} + onEmail={() => dispatch({ type: 'choose-email' })} + /> + ); + case 'google-wait': + return ; + case 'auth-pending': + return ( +
+
+

Finishing sign in

+ {state.url && ( + + Not redirected? Continue with Google + + )} +
+ ); + case 'email-entry': + return ( + { + void postAction(session, { type: 'email', email }).then((ok) => { + if (ok) dispatch({ type: 'submit-email', email }); + }); + }} + onBack={() => dispatch({ type: 'back' })} + /> + ); + case 'email-wait': + return ; + case 'otp-entry': + return ( + { + void postAction(session, { type: 'otp', code }).then((ok) => { + if (ok) dispatch({ type: 'submit-otp', code }); + }); + }} + /> + ); + case 'otp-wait': + return ; + case 'success': + return ( +
+

You're signed in

+

Wallet {state.walletAddress}

+

+ Your terminal session is ready. Taking you to your dashboard. +

+ + Not redirected? Open your dashboard + +
+ ); + case 'expired': + return ( +
+

This link has expired

+

+ Run{' '} + agent wallet login{' '} + again to get a fresh link. +

+
+ ); + case 'failed': + return ( +
+

Sign in failed

+

{state.message}

+

+ Check your terminal for details and re-run the login. +

+
+ ); + } +} + +function GoogleLogo() { + return ( + + ); +} + +function MethodChoice({ onGoogle, onEmail }: { onGoogle: () => void; onEmail: () => void }) { + return ( +
+

+ Sign in to your agent wallet +

+

+ This connects to your agent in your terminal. +

+ + +
+ ); +} + +function EmailForm({ + onSubmit, + onBack +}: { + onSubmit: (email: string) => void; + onBack: () => void; +}) { + const [email, setEmail] = useState(''); + return ( +
{ + e.preventDefault(); + if (email.includes('@')) onSubmit(email.trim()); + }} + > +

Sign in with email

+ setEmail(e.target.value)} + placeholder="you@example.com" + className="mt-6 w-full rounded-xl border border-[#c8cfe1] px-4 py-3 text-sm text-[#141635] outline-none focus:border-[#141635]" + /> + + +
+ ); +} + +function OtpForm({ + invalid, + attemptsLeft, + onSubmit +}: { + invalid?: boolean; + attemptsLeft?: number; + onSubmit: (code: string) => void; +}) { + const [code, setCode] = useState(''); + return ( +
{ + e.preventDefault(); + if (code.trim().length >= 4) onSubmit(code.trim()); + }} + > +

Enter your code

+

+ We sent a one-time code to your email. +

+ {invalid && ( +

+ That code didn't work + {typeof attemptsLeft === 'number' ? ` (${attemptsLeft} attempts left)` : ''}. Try again. +

+ )} + setCode(e.target.value)} + placeholder="123456" + className="mt-6 w-full rounded-xl border border-[#c8cfe1] px-4 py-3 text-center text-lg tracking-[0.3em] text-[#141635] outline-none focus:border-[#141635]" + /> + +
+ ); +} + +function Waiting({ text }: { text: string }) { + return ( +
+
+

{text}

+
+ ); +} diff --git a/packages/agentconnect-ui/src/login/machine.test.ts b/packages/agentconnect-ui/src/login/machine.test.ts new file mode 100644 index 0000000..2daa9d9 --- /dev/null +++ b/packages/agentconnect-ui/src/login/machine.test.ts @@ -0,0 +1,143 @@ +import { describe, expect, it } from 'vitest'; + +import type { MachineState } from './machine.ts'; + +import { initialState, reduce } from './machine.ts'; + +describe('login machine', () => { + it('google: method -> google-wait -> success', () => { + let s: MachineState = initialState; + s = reduce(s, { type: 'choose-google' }); + expect(s).toEqual({ kind: 'google-wait' }); + s = reduce(s, { type: 'status', status: { status: 'done', walletAddress: '0xW' } }); + expect(s).toEqual({ kind: 'success', walletAddress: '0xW' }); + }); + + it('email: full path with an otp retry', () => { + let s: MachineState = initialState; + s = reduce(s, { type: 'choose-email' }); + expect(s).toEqual({ kind: 'email-entry' }); + s = reduce(s, { type: 'submit-email', email: 'a@b.co' }); + expect(s).toEqual({ kind: 'email-wait', email: 'a@b.co' }); + s = reduce(s, { type: 'status', status: { status: 'otp-sent' } }); + expect(s).toEqual({ kind: 'otp-entry', email: 'a@b.co' }); + s = reduce(s, { type: 'submit-otp', code: '111111' }); + expect(s).toEqual({ kind: 'otp-wait', email: 'a@b.co' }); + s = reduce(s, { type: 'status', status: { status: 'otp-invalid', attemptsLeft: 2 } }); + expect(s).toEqual({ kind: 'otp-entry', email: 'a@b.co', attemptsLeft: 2, invalid: true }); + s = reduce(s, { type: 'submit-otp', code: '222222' }); + s = reduce(s, { type: 'status', status: { status: 'done', walletAddress: '0xW' } }); + expect(s).toEqual({ kind: 'success', walletAddress: '0xW' }); + }); + + it('expired and error statuses are terminal from any state', () => { + expect(reduce(initialState, { type: 'status', status: { status: 'expired' } })).toEqual({ + kind: 'expired' + }); + expect( + reduce( + { kind: 'otp-wait', email: 'a@b.co' }, + { type: 'status', status: { status: 'error', message: 'boom' } } + ) + ).toEqual({ kind: 'failed', message: 'boom' }); + }); + + it('reconciles a refreshed page from the polled status', () => { + // After a refresh the page is back at `method`; the poll snaps it forward. + expect(reduce(initialState, { type: 'status', status: { status: 'otp-sent' } })).toEqual({ + kind: 'otp-entry', + email: '' + }); + expect( + reduce(initialState, { type: 'status', status: { status: 'done', walletAddress: '0xW' } }) + ).toEqual({ kind: 'success', walletAddress: '0xW' }); + // A refresh can also land after an invalid code was already reported; + // the poll snaps straight to the otp form with the invalid flag set. + expect(reduce(initialState, { type: 'status', status: { status: 'otp-invalid' } })).toEqual({ + kind: 'otp-entry', + email: '', + invalid: true + }); + }); + + it('back returns from email entry to method choice', () => { + expect(reduce({ kind: 'email-entry' }, { type: 'back' })).toEqual({ kind: 'method' }); + }); + + it('awaiting-method and stale statuses do not regress the ui', () => { + expect( + reduce({ kind: 'email-entry' }, { type: 'status', status: { status: 'awaiting-method' } }) + ).toEqual({ kind: 'email-entry' }); + // From google-wait the component auto-redirects as a side effect; state is unchanged. + expect( + reduce( + { kind: 'google-wait' }, + { type: 'status', status: { status: 'auth-url', url: 'https://x' } } + ) + ).toEqual({ kind: 'google-wait' }); + }); + + it('auth-url from method moves to auth-pending with the url', () => { + expect( + reduce(initialState, { type: 'status', status: { status: 'auth-url', url: 'https://x' } }) + ).toEqual({ kind: 'auth-pending', url: 'https://x' }); + }); + + it('auth-pending only exits via a terminal status', () => { + const authPending: MachineState = { kind: 'auth-pending', url: 'https://x' }; + expect( + reduce(authPending, { type: 'status', status: { status: 'done', walletAddress: '0xW' } }) + ).toEqual({ kind: 'success', walletAddress: '0xW' }); + expect(reduce(authPending, { type: 'status', status: { status: 'otp-sent' } })).toEqual( + authPending + ); + }); + + it('relay-return on initial load moves straight to auth-pending, no url', () => { + expect(reduce(initialState, { type: 'relay-return' })).toEqual({ kind: 'auth-pending' }); + }); + + it('relay-return is a no-op once past the method chooser', () => { + expect(reduce({ kind: 'google-wait' }, { type: 'relay-return' })).toEqual({ + kind: 'google-wait' + }); + expect(reduce({ kind: 'email-entry' }, { type: 'relay-return' })).toEqual({ + kind: 'email-entry' + }); + }); + + it('the finishing state reached via relay-return only exits via a terminal status', () => { + const finishing: MachineState = reduce(initialState, { type: 'relay-return' }); + expect( + reduce(finishing, { type: 'status', status: { status: 'done', walletAddress: '0xW' } }) + ).toEqual({ kind: 'success', walletAddress: '0xW' }); + expect(reduce(finishing, { type: 'status', status: { status: 'otp-sent' } })).toEqual( + finishing + ); + }); + + it('terminal states absorb any later status or event', () => { + const success: MachineState = { kind: 'success', walletAddress: '0xW' }; + expect(reduce(success, { type: 'status', status: { status: 'otp-sent' } })).toEqual(success); + expect( + reduce( + { kind: 'failed', message: 'boom' }, + { type: 'status', status: { status: 'done', walletAddress: '0xW' } } + ) + ).toEqual({ kind: 'failed', message: 'boom' }); + expect(reduce({ kind: 'expired' }, { type: 'choose-google' })).toEqual({ kind: 'expired' }); + }); + + it('user events from illegal states are no-ops', () => { + expect(reduce({ kind: 'email-entry' }, { type: 'submit-otp', code: '123456' })).toEqual({ + kind: 'email-entry' + }); + expect(reduce({ kind: 'otp-entry', email: 'a@b.co' }, { type: 'choose-google' })).toEqual({ + kind: 'otp-entry', + email: 'a@b.co' + }); + expect(reduce(initialState, { type: 'submit-email', email: 'a@b.co' })).toEqual({ + kind: 'method' + }); + }); +}); diff --git a/packages/agentconnect-ui/src/login/machine.ts b/packages/agentconnect-ui/src/login/machine.ts new file mode 100644 index 0000000..9197cdb --- /dev/null +++ b/packages/agentconnect-ui/src/login/machine.ts @@ -0,0 +1,116 @@ +// Pure state machine for the /login page. The component polls the relay and +// feeds statuses in as events alongside user input; side effects (posting +// actions, redirecting to the auth url) live in the component, not here. + +export type LoginStatus = + | { status: 'awaiting-method' } + | { status: 'auth-url'; url: string } + | { status: 'otp-sent' } + | { status: 'otp-invalid'; attemptsLeft?: number } + | { status: 'done'; walletAddress: string } + | { status: 'error'; message: string }; + +export type RelayStatus = LoginStatus | { status: 'expired' }; + +export type MachineState = + | { kind: 'method' } + | { kind: 'google-wait' } + // `url` is present when this came from a live `auth-url` status (offers a + // manual fallback link); absent when the page detected a relay return on + // load, since there is nothing left to link to at that point. + | { kind: 'auth-pending'; url?: string } + | { kind: 'email-entry' } + | { kind: 'email-wait'; email: string } + | { kind: 'otp-entry'; email: string; invalid?: boolean; attemptsLeft?: number } + | { kind: 'otp-wait'; email: string } + | { kind: 'success'; walletAddress: string } + | { kind: 'expired' } + | { kind: 'failed'; message: string }; + +export type MachineEvent = + | { type: 'status'; status: RelayStatus } + | { type: 'choose-google' } + | { type: 'choose-email' } + | { type: 'submit-email'; email: string } + | { type: 'submit-otp'; code: string } + | { type: 'back' } + // Fired once on initial mount when the page detects it was just returned to + // from the OMS relay (as opposed to a fresh open). Skips the method chooser + // and goes straight to the finishing spinner. + | { type: 'relay-return' }; + +export type LoginAction = + | { type: 'google' } + | { type: 'email'; email: string } + | { type: 'otp'; code: string } + | { type: 'cancel' } + | { type: 'oidc-callback'; callbackUrl: string }; + +export const initialState: MachineState = { kind: 'method' }; + +function emailOf(state: MachineState): string { + return 'email' in state ? state.email : ''; +} + +export function reduce(state: MachineState, event: MachineEvent): MachineState { + // Terminal states absorb everything: a stale or duplicate poll response must + // never regress the ui once the flow has resolved. + if (state.kind === 'success' || state.kind === 'expired' || state.kind === 'failed') { + return state; + } + + if (event.type === 'status') { + const s = event.status; + // Terminal statuses win from anywhere. + if (s.status === 'expired') return { kind: 'expired' }; + if (s.status === 'error') return { kind: 'failed', message: s.message }; + if (s.status === 'done') return { kind: 'success', walletAddress: s.walletAddress }; + + // auth-pending only exits via a terminal status (handled above): once the + // page is waiting out the Google redirect there is nothing else worth + // reacting to until sign-in finishes or fails. + if (state.kind === 'auth-pending') return state; + + // otp-sent snaps forward (also reconciles a refreshed page). + if (s.status === 'otp-sent') { + if (state.kind === 'otp-entry' || state.kind === 'otp-wait') return state; + return { kind: 'otp-entry', email: emailOf(state) }; + } + // otp-invalid snaps forward from anywhere that isn't already on the otp + // form, reconciling a refreshed or lagging page onto the invalid-code + // message instead of leaving it stuck on an earlier step. + if (s.status === 'otp-invalid') { + if (state.kind === 'otp-entry') return state; + return { + kind: 'otp-entry', + email: emailOf(state), + invalid: true, + attemptsLeft: s.attemptsLeft + }; + } + // auth-url on a fresh or refreshed page (still at `method`) must not show + // the live method buttons while a Google redirect is in flight, so it + // moves to a distinct waiting state with a manual fallback link. From + // google-wait the component itself auto-redirects, so state is unchanged. + if (s.status === 'auth-url' && state.kind === 'method') { + return { kind: 'auth-pending', url: s.url }; + } + // awaiting-method and auth-url (from any other state) never regress the ui. + return state; + } + + switch (event.type) { + case 'choose-google': + return state.kind === 'method' ? { kind: 'google-wait' } : state; + case 'choose-email': + return state.kind === 'method' ? { kind: 'email-entry' } : state; + case 'submit-email': + return state.kind === 'email-entry' ? { kind: 'email-wait', email: event.email } : state; + case 'submit-otp': + return state.kind === 'otp-entry' ? { kind: 'otp-wait', email: state.email } : state; + case 'back': + return state.kind === 'email-entry' ? { kind: 'method' } : state; + case 'relay-return': + return state.kind === 'method' ? { kind: 'auth-pending' } : state; + } +} diff --git a/packages/agentconnect-ui/src/login/returnUrl.test.ts b/packages/agentconnect-ui/src/login/returnUrl.test.ts new file mode 100644 index 0000000..a7e0670 --- /dev/null +++ b/packages/agentconnect-ui/src/login/returnUrl.test.ts @@ -0,0 +1,55 @@ +import { describe, expect, it } from 'vitest'; + +import { getSessionId, isRelayReturn } from './returnUrl.ts'; + +describe('getSessionId', () => { + it('reads the session from the query string', () => { + expect(getSessionId('?s=abc', '')).toBe('abc'); + }); + + it('falls back to the fragment when there is no query', () => { + expect(getSessionId('', '#abc')).toBe('abc'); + }); + + it('prefers the query over the fragment when both are present', () => { + expect(getSessionId('?s=abc', '#xyz')).toBe('abc'); + }); + + it('returns an empty string when neither is present', () => { + expect(getSessionId('', '')).toBe(''); + }); +}); + +describe('isRelayReturn', () => { + it('is false for a fragment-only announce link (no query at all)', () => { + expect(isRelayReturn('#abc')).toBe(false); + }); + + it('is true for a bare oauth callback param, no `s` needed', () => { + expect(isRelayReturn('?code=xyz')).toBe(true); + }); + + it('is true when `s` and an oauth callback param are both present', () => { + expect(isRelayReturn('?s=abc&code=xyz')).toBe(true); + }); + + it('is true for a bare `state` param', () => { + expect(isRelayReturn('?state=1')).toBe(true); + }); + + it('is true when the relay reports an oauth error', () => { + expect(isRelayReturn('?error=access_denied')).toBe(true); + }); + + it('is false for `s` alongside a non-oauth query param', () => { + expect(isRelayReturn('?s=abc&utm_source=x')).toBe(false); + }); + + it('is false for a non-oauth query param with no `s`', () => { + expect(isRelayReturn('?utm_source=x')).toBe(false); + }); + + it('is false for an empty query string', () => { + expect(isRelayReturn('')).toBe(false); + }); +}); diff --git a/packages/agentconnect-ui/src/login/returnUrl.ts b/packages/agentconnect-ui/src/login/returnUrl.ts new file mode 100644 index 0000000..d89359e --- /dev/null +++ b/packages/agentconnect-ui/src/login/returnUrl.ts @@ -0,0 +1,46 @@ +// Pure helpers for detecting the login page's session id and whether the +// load is a bounce back from the OMS relay. Kept free of `window` so they can +// be unit tested directly; the component passes in `location.search` and +// `location.hash`. +// +// Two distinct url shapes land on this page: +// - CLI announce: `/login#` (fragment). The CLI opens this in the +// user's browser with nothing to lose by putting the session in the +// fragment, since there is no round trip through a third party. +// - Relay return: `/login?` (query only, e.g. `code`, `state`). +// The return URI registered with the OMS relay must be the bare, static +// `/login` to satisfy its allowlist (an exact-string match), so it can no +// longer carry `?s=`. The pairing session is instead stashed in +// sessionStorage by the component before the redirect to Google, and +// recovered from there when the browser bounces back; these helpers only +// see the query/fragment, not sessionStorage. + +// Session id lives in the `?s=` query param (used for the legacy relay +// return shape, and still supported); the `#` fragment is the primary +// carrier for the CLI announce link. On an OMS relay return neither is +// present, since the return URI is now the bare, static `/login` — the +// component falls back to sessionStorage in that case. +export function getSessionId(search: string, hash: string): string { + const fromQuery = new URLSearchParams(search).get('s'); + if (fromQuery) return fromQuery; + return hash.slice(1); +} + +// The OAuth callback params the OMS relay appends to the return URL once +// Google sign-in bounces back through it. The SDK consumes these directly +// from the query string, so their presence is what actually distinguishes a +// relay return from a fresh open. +const OAUTH_CALLBACK_PARAMS = ['code', 'state', 'error']; + +// True when this load is the browser bouncing back from the OMS relay after +// Google sign-in, not a fresh open. We key specifically on the OAuth callback +// params (`code`, `state`, `error`) the relay appends to the static `/login` +// return URI, rather than on "any other query key present": a link wrapper or +// ad click can append tracking params (`utm_*`, `gclid`, etc.) to a pasted +// `/login?...` link, and that must not be mistaken for a relay return that +// posts a bogus callback to the relay. This no longer requires `s` alongside +// them, since the return URI is static and never carries it. +export function isRelayReturn(search: string): boolean { + const params = new URLSearchParams(search); + return OAUTH_CALLBACK_PARAMS.some((key) => params.has(key)); +} diff --git a/packages/connector-ui/src/main.tsx b/packages/agentconnect-ui/src/main.tsx similarity index 100% rename from packages/connector-ui/src/main.tsx rename to packages/agentconnect-ui/src/main.tsx diff --git a/packages/connector-ui/src/vite-env.d.ts b/packages/agentconnect-ui/src/vite-env.d.ts similarity index 100% rename from packages/connector-ui/src/vite-env.d.ts rename to packages/agentconnect-ui/src/vite-env.d.ts diff --git a/packages/connector-ui/tsconfig.app.json b/packages/agentconnect-ui/tsconfig.app.json similarity index 100% rename from packages/connector-ui/tsconfig.app.json rename to packages/agentconnect-ui/tsconfig.app.json diff --git a/packages/connector-ui/tsconfig.json b/packages/agentconnect-ui/tsconfig.json similarity index 100% rename from packages/connector-ui/tsconfig.json rename to packages/agentconnect-ui/tsconfig.json diff --git a/packages/connector-ui/tsconfig.node.json b/packages/agentconnect-ui/tsconfig.node.json similarity index 88% rename from packages/connector-ui/tsconfig.node.json rename to packages/agentconnect-ui/tsconfig.node.json index 98f5e42..0d3d714 100644 --- a/packages/connector-ui/tsconfig.node.json +++ b/packages/agentconnect-ui/tsconfig.node.json @@ -18,5 +18,5 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["vite.config.ts", "vite-plugins/**/*.ts"] + "include": ["vite.config.ts"] } diff --git a/packages/connector-ui/vite.config.ts b/packages/agentconnect-ui/vite.config.ts similarity index 65% rename from packages/connector-ui/vite.config.ts rename to packages/agentconnect-ui/vite.config.ts index 1db9486..7006f31 100644 --- a/packages/connector-ui/vite.config.ts +++ b/packages/agentconnect-ui/vite.config.ts @@ -2,11 +2,9 @@ import tailwindcss from '@tailwindcss/vite'; import react from '@vitejs/plugin-react'; import { defineConfig } from 'vite'; -import { mirrorSkills } from './vite-plugins/mirror-skills'; - // https://vite.dev/config/ export default defineConfig({ - plugins: [react(), tailwindcss(), mirrorSkills()], + plugins: [react(), tailwindcss()], server: { port: 4444 } diff --git a/packages/connector-ui/worker.mjs b/packages/agentconnect-ui/worker.mjs similarity index 59% rename from packages/connector-ui/worker.mjs rename to packages/agentconnect-ui/worker.mjs index 9376bc9..bc94180 100644 --- a/packages/connector-ui/worker.mjs +++ b/packages/agentconnect-ui/worker.mjs @@ -1,22 +1,14 @@ -// packages/connector-ui/worker.mjs -import { handleRelayRequest, SessionRelay } from './src/relay.ts'; - -export { SessionRelay }; - +// packages/agentconnect-ui/worker.mjs +// Serves the built SPA from the ASSETS binding with single-page-application fallback. export default { async fetch(request, env) { const url = new URL(request.url); - // Route /api/relay/* to Durable Object relay - if (url.pathname.startsWith('/api/relay')) { - return handleRelayRequest(request, env); - } - if (!env.ASSETS) { return new Response('ASSETS binding is missing', { status: 500 }); } - // SPA fallback: serve index.html for non-file paths + // SPA fallback: serve index.html for non-file paths. const res = await env.ASSETS.fetch(request); if (res.status !== 404) return res; diff --git a/packages/connector-ui/wrangler.toml b/packages/agentconnect-ui/wrangler.toml similarity index 59% rename from packages/connector-ui/wrangler.toml rename to packages/agentconnect-ui/wrangler.toml index b9161b3..929a9df 100644 --- a/packages/connector-ui/wrangler.toml +++ b/packages/agentconnect-ui/wrangler.toml @@ -11,15 +11,11 @@ main = "worker.mjs" directory = "./dist" binding = "ASSETS" not_found_handling = "single-page-application" -run_worker_first = ["/api/*"] - -[[durable_objects.bindings]] -name = "SESSION_RELAY" -class_name = "SessionRelay" +# Drop the old SessionRelay Durable Object carried over from connector-ui. [[migrations]] -tag = "v1" -new_classes = ["SessionRelay"] +tag = "v2" +deleted_classes = ["SessionRelay"] [env.staging] name = "agentconnect-staging" @@ -28,13 +24,9 @@ routes = [ { pattern = "agentconnect.staging.polygon.technology", custom_domain = true } ] -[[env.staging.durable_objects.bindings]] -name = "SESSION_RELAY" -class_name = "SessionRelay" - [[env.staging.migrations]] -tag = "v1" -new_classes = ["SessionRelay"] +tag = "v2" +deleted_classes = ["SessionRelay"] [env.production] name = "agentconnect-production" @@ -43,11 +35,6 @@ routes = [ { pattern = "agentconnect.polygon.technology", custom_domain = true } ] -[[env.production.durable_objects.bindings]] -name = "SESSION_RELAY" -class_name = "SessionRelay" - [[env.production.migrations]] -tag = "v1" -new_classes = ["SessionRelay"] - +tag = "v2" +deleted_classes = ["SessionRelay"] diff --git a/packages/connector-ui/.env.example b/packages/connector-ui/.env.example deleted file mode 100644 index 4f44233..0000000 --- a/packages/connector-ui/.env.example +++ /dev/null @@ -1,21 +0,0 @@ -# Copy to .env and fill values. -# Get Project Access Key from https://sequence.build (create a project + enable Ecosystem Wallet / v3). -VITE_PROJECT_ACCESS_KEY= - -# Ecosystem wallet URL (given) -# IMPORTANT: no trailing slash -VITE_WALLET_URL=https://dev-polygon-wallet.ecosystem-demo.xyz - -# The origin of this dapp (used by dapp-client) -# Leave empty to default to window.location.origin. -VITE_DAPP_ORIGIN= - -# Optional infra overrides -VITE_RELAYER_URL=https://dev-{network}-relayer.sequence.app -VITE_NODES_URL= - -# Optional: used to show balances in the UI via Sequence indexer (multi-chain). -VITE_INDEXER_ACCESS_KEY= - -# Back-compat (deprecated): -# VITE_POLYGON_INDEXER_ACCESS_KEY= diff --git a/packages/connector-ui/CHANGELOG.md b/packages/connector-ui/CHANGELOG.md deleted file mode 100644 index 4c92c18..0000000 --- a/packages/connector-ui/CHANGELOG.md +++ /dev/null @@ -1,380 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [1.6.16](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.15...@polygonlabs/agent-connector-ui@1.6.16) (2026-06-09) - -**Note:** Version bump only for package @polygonlabs/agent-connector-ui - - - - - -## [1.6.15](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.13...@polygonlabs/agent-connector-ui@1.6.15) (2026-05-27) - - -### Bug Fixes - -* **connector-ui:** let --contract override auto-injected fee-token permissions ([1f446f1](https://github.com/0xPolygon/polygon-agent-cli/commit/1f446f171db5b16672bb862ccb4c02a3f4348807)) -* **skills:** require discovery sub-skill load before x402 calls; bump connector-ui ([c72c080](https://github.com/0xPolygon/polygon-agent-cli/commit/c72c080d02adee47aa306d81def1c1251adc4539)) - - - - - -## [1.6.13](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.12...@polygonlabs/agent-connector-ui@1.6.13) (2026-04-30) - -**Note:** Version bump only for package @polygonlabs/agent-connector-ui - - - - - -## [1.6.12](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.10...@polygonlabs/agent-connector-ui@1.6.12) (2026-04-29) - - -### Bug Fixes - -* auto-whitelist Aave V3 Pool, enforce 0.1 gas reserve on deposit ([d7db76b](https://github.com/0xPolygon/polygon-agent-cli/commit/d7db76b1cd202fbe14d45e18c3fc2b23883907a6)) - - - - - -## [1.6.10](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.8...@polygonlabs/agent-connector-ui@1.6.10) (2026-04-29) - - -### Bug Fixes - -* **connector-ui:** remove from prop missing required chain field ([fa32be9](https://github.com/0xPolygon/polygon-agent-cli/commit/fa32be9f8e1ff7b1763c3b35a6df23d78f852774)) - - - - - -## [1.6.8](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.6...@polygonlabs/agent-connector-ui@1.6.8) (2026-04-28) - -**Note:** Version bump only for package @polygonlabs/agent-connector-ui - - - - - -## [1.6.6](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.4...@polygonlabs/agent-connector-ui@1.6.6) (2026-04-27) - - -### Bug Fixes - -* **wallet:** scope default session whitelist to USDC/USDC.e; add --defi flag ([f8c9256](https://github.com/0xPolygon/polygon-agent-cli/commit/f8c92566a26257554c585555a5ff6dd6fd9ee591)) - - - - - -## [1.6.4](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.3...@polygonlabs/agent-connector-ui@1.6.4) (2026-04-27) - - -### Bug Fixes - -* **deposit:** pre-flight balance checks, gas reserve, session guard, and actionable errors ([8011838](https://github.com/0xPolygon/polygon-agent-cli/commit/8011838f1ded843fc9666d0f3cb215e8cf871701)) - - - - - -## [1.6.3](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.2...@polygonlabs/agent-connector-ui@1.6.3) (2026-04-22) - -**Note:** Version bump only for package @polygonlabs/agent-connector-ui - - - - - -## [1.6.2](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.1...@polygonlabs/agent-connector-ui@1.6.2) (2026-04-22) - -**Note:** Version bump only for package @polygonlabs/agent-connector-ui - - - - - -## [1.6.1](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.6.0...@polygonlabs/agent-connector-ui@1.6.1) (2026-04-21) - -**Note:** Version bump only for package @polygonlabs/agent-connector-ui - - - - - -# [1.6.0](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.5.0...@polygonlabs/agent-connector-ui@1.6.0) (2026-04-21) - - -### Bug Fixes - -* **deposit:** whitelist ERC-20 token contracts and fix session error messages ([1beb54b](https://github.com/0xPolygon/polygon-agent-cli/commit/1beb54b61012c4661b3aa9602bb172b3e2c3c7d6)) -* restore connector skill URL sync (polygon-* public copies + husky) ([d979216](https://github.com/0xPolygon/polygon-agent-cli/commit/d97921674df79dbb616c31de60b4ac1b8028689b)) -* smart wallet usdc transfer limits and permissions order ([83e7f2c](https://github.com/0xPolygon/polygon-agent-cli/commit/83e7f2cf281390fbb019d78008a55245ca03fd1d)) - - -### Features - -* **cli:** add --chains comma list for balances ([0a4f50c](https://github.com/0xPolygon/polygon-agent-cli/commit/0a4f50c1f8c71b9cc4cf9fb15cd46b4c4181a4c1)) -* **cli:** add withdraw for Aave aTokens and ERC-4626 vaults ([494ccbc](https://github.com/0xPolygon/polygon-agent-cli/commit/494ccbc3e65c0a2cf87ed22794431cfcc47e183d)) -* **cli:** drop bundled skills and sync hook ([d9872eb](https://github.com/0xPolygon/polygon-agent-cli/commit/d9872ebc8c7d0422af4e871e8e84d04080962f5a)) - - - - - -# [1.5.0](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.4.2...@polygonlabs/agent-connector-ui@1.5.0) (2026-04-16) - - -### Bug Fixes - -* **skills:** fix Twitter/X x402 endpoint in polygon-discovery ([8f667f9](https://github.com/0xPolygon/polygon-agent-cli/commit/8f667f97f8b51c26d95e77de37c6b8877b5a759b)) -* **skills:** rename to "Polygon Agent" and fix Twitter/X x402 endpoint ([7909791](https://github.com/0xPolygon/polygon-agent-cli/commit/7909791aa715a3ed5a6aecdf5a0d35d5cf17b9c0)) -* **skills:** serve sub-skills at root paths on agentconnect domain ([8d3b042](https://github.com/0xPolygon/polygon-agent-cli/commit/8d3b042e815a485af0582af60d791c15a37249d0)) -* **skills:** sync root public/SKILL.md in pre-commit hook ([0e7c291](https://github.com/0xPolygon/polygon-agent-cli/commit/0e7c291c440112c15813ea907aa19dc20d88ae02)) -* **skills:** sync root public/SKILL.md to use sub-skill URLs ([0c748fb](https://github.com/0xPolygon/polygon-agent-cli/commit/0c748fb29f3719b2c1d3b8e89a17808465268a41)) -* **skills:** update install command to npm install -g @polygonlabs/agent-cli ([e0ac8cb](https://github.com/0xPolygon/polygon-agent-cli/commit/e0ac8cb34212f9b4b24b22ea1fa6c3416744cc1a)) -* **skills:** update Twitter/X description to follower/following counts and tweet metrics ([7dcfb29](https://github.com/0xPolygon/polygon-agent-cli/commit/7dcfb29d4e5b8c8b5c7227835ce84118adca7b47)) -* **skills:** use absolute URLs for sub-skill discovery ([12a8d14](https://github.com/0xPolygon/polygon-agent-cli/commit/12a8d145363bd4749b628e2b94d497e7fa12cba7)) - - -### Features - -* **skill:** add prerequisites check to polygon-discovery skill ([d16d6fa](https://github.com/0xPolygon/polygon-agent-cli/commit/d16d6fa8f1eff21f2338550d4f0acc40fc7248a3)) -* **skills:** add getEarnPools API reference to polygon-defi skill ([a175c26](https://github.com/0xPolygon/polygon-agent-cli/commit/a175c2670914ad618541ab3dc8d56fac374e03a3)) -* **skills:** add getEarnPools API reference to polygon-defi skill ([411d831](https://github.com/0xPolygon/polygon-agent-cli/commit/411d831fe5c43881f1aaa3e07b20359a79e3c673)) - - - - - -## [1.4.2](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.4.1...@polygonlabs/agent-connector-ui@1.4.2) (2026-04-14) - - -### Bug Fixes - -* **ci:** add --access public to lerna publish for scoped packages ([c157790](https://github.com/0xPolygon/polygon-agent-cli/commit/c1577907f1363e5a173e6f49321c545395260fb9)) -* **cli:** bundle agent-shared into CLI instead of publishing to npm ([1cc2d7b](https://github.com/0xPolygon/polygon-agent-cli/commit/1cc2d7b28b971f7b4b85d9473393c9fce92edd57)) - - - - - -## [1.4.1](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.4.0...@polygonlabs/agent-connector-ui@1.4.1) (2026-04-14) - -**Note:** Version bump only for package @polygonlabs/agent-connector-ui - - - - - -# [1.4.0](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.0.2...@polygonlabs/agent-connector-ui@1.4.0) (2026-04-14) - - -### Bug Fixes - -* address code review issues — persist cliSk, raise payload limit, validate inputs, cleanup ([f38d2f2](https://github.com/0xPolygon/polygon-agent-cli/commit/f38d2f2afc59122655e46274e201016c0f4240f2)) -* **connector-ui:** add @cloudflare/workers-types for relay DO type resolution ([5e9a070](https://github.com/0xPolygon/polygon-agent-cli/commit/5e9a070b8141687bbc3a95b813b32d7af7b4ad89)) -* **connector-ui:** add quotes around claude command argument and lowercase prefix ([0cfc441](https://github.com/0xPolygon/polygon-agent-cli/commit/0cfc44195e4a1b737be7544f7284632b74ed8f32)) -* **connector-ui:** add SESSION_RELAY DO bindings to staging and production envs ([16fe31e](https://github.com/0xPolygon/polygon-agent-cli/commit/16fe31ef82972ba7840c2881fc71eb5ee5a0fbe2)) -* **connector-ui:** align subtext color to [#6](https://github.com/0xPolygon/polygon-agent-cli/issues/6)b7280 across landing and code screens ([29f7336](https://github.com/0xPolygon/polygon-agent-cli/commit/29f733651f8eb4c5986ad94ffcdcff22d2b38ba0)), closes [#6b7280](https://github.com/0xPolygon/polygon-agent-cli/issues/6b7280) -* **connector-ui:** extend session deadline to 6 months ([cb843b0](https://github.com/0xPolygon/polygon-agent-cli/commit/cb843b05512d326e241cbaab25a93dffb5a94364)) -* **connector-ui:** fix logo to top of screen on all flow screens ([4316ae8](https://github.com/0xPolygon/polygon-agent-cli/commit/4316ae875116dd04af9cd52454179185a6bd8efe)) -* **connector-ui:** fixed centered logo+badge on screens 1-3, onchain spelling ([e687bce](https://github.com/0xPolygon/polygon-agent-cli/commit/e687bce7fd9df1f3540b571da8ce18acc57da57a)) -* **connector-ui:** preserve implicit session metadata, remove tweetnacl, add rid validation ([ca4c4aa](https://github.com/0xPolygon/polygon-agent-cli/commit/ca4c4aa7ce972639e80b3fe4c8cc6abd01db3df1)) -* **connector-ui:** relay init error check, rid validation, re-init guard, payload size limit ([509b34f](https://github.com/0xPolygon/polygon-agent-cli/commit/509b34f593478b3b8e4f4c1cdb02ca355e55379c)) -* **connector-ui:** remove dollar sign from terminal prefix display ([da70d5f](https://github.com/0xPolygon/polygon-agent-cli/commit/da70d5ffbdbb099d873751e87c046611b39189ce)) -* **connector-ui:** remove dollar sign prefix from copied commands ([d8bb2e1](https://github.com/0xPolygon/polygon-agent-cli/commit/d8bb2e1e290f2f57bdc848c894f4dd2be512d5f2)) -* **connector-ui:** remove services list card from dashboard ([be3ee92](https://github.com/0xPolygon/polygon-agent-cli/commit/be3ee92ff1ee42d00cc97d0fdb4b7e45a26bd555)) -* **connector-ui:** restore >_ agent mono badge on all screens ([d753dd7](https://github.com/0xPolygon/polygon-agent-cli/commit/d753dd72e3c866040f618c8a0262e331681ea9b7)) -* **relay:** include code_hash_hex in retrieve response for CLI decryption ([0b713b8](https://github.com/0xPolygon/polygon-agent-cli/commit/0b713b8f380b2f928a0575cc7f2c311177d61d8a)) -* **skills:** quote SKILL.md description to fix YAML colon parse error ([79e1f65](https://github.com/0xPolygon/polygon-agent-cli/commit/79e1f6542f4faed33f8aa4b4db6aa79dc99902db)) -* **skills:** update x402 Bazaar endpoints to use POST, update Twitter prompt ([cee084d](https://github.com/0xPolygon/polygon-agent-cli/commit/cee084dc1bdc5dbfffca6209a8734679c8741e82)) -* **ui:** shorten lead scoring display text, fix duplicate Target icon ([dd3c976](https://github.com/0xPolygon/polygon-agent-cli/commit/dd3c9761878bbabc377baa7e23a253f484fa000a)) -* **x402-pay:** align payment_details handler with x402 Bazaar integration guide ([c3a751e](https://github.com/0xPolygon/polygon-agent-cli/commit/c3a751e1689b6f1dfc3155b30e13de19ec4ca686)) -* **x402-pay:** implement EIP-3009 facilitator path for Polygon payment_details ([42d4d05](https://github.com/0xPolygon/polygon-agent-cli/commit/42d4d05bebe059e7c0ab617f12e88f2411ee0e15)) - - -### Features - -* **cli:** ink UI redesign and DX improvements ([8ad6596](https://github.com/0xPolygon/polygon-agent-cli/commit/8ad6596448b75590d699c1bcf3fa332c73750b7f)) -* **connector-ui:** add Durable Object relay API + upgrade worker routing ([77a093c](https://github.com/0xPolygon/polygon-agent-cli/commit/77a093cbad4e136fd9ada94da8a667b5ff08a26a)) -* **connector-ui:** add Openclaw and Hermes agent options ([e18b076](https://github.com/0xPolygon/polygon-agent-cli/commit/e18b076071ead7223d49732c0202e03f7456a94b)) -* **connector-ui:** apply OMSX Figma design system to all screens ([154afbd](https://github.com/0xPolygon/polygon-agent-cli/commit/154afbd28b818add730edc6d3879548b3e5a3743)), closes [#141635](https://github.com/0xPolygon/polygon-agent-cli/issues/141635) [#64708](https://github.com/0xPolygon/polygon-agent-cli/issues/64708) [#c8cfe1](https://github.com/0xPolygon/polygon-agent-cli/issues/c8cfe1) [#929](https://github.com/0xPolygon/polygon-agent-cli/issues/929) [#141635](https://github.com/0xPolygon/polygon-agent-cli/issues/141635) [#7c3](https://github.com/0xPolygon/polygon-agent-cli/issues/7c3) [#f5f6](https://github.com/0xPolygon/polygon-agent-cli/issues/f5f6) [#929](https://github.com/0xPolygon/polygon-agent-cli/issues/929) -* **connector-ui:** enable Mesh onramp in production for TrailsWidget ([93e562b](https://github.com/0xPolygon/polygon-agent-cli/commit/93e562b70c136e5f9bdeb5786df09b63798778c0)) -* **connector-ui:** redesign — light theme, code display, funding flow ([63b2fcd](https://github.com/0xPolygon/polygon-agent-cli/commit/63b2fcdf7cb46b44d76e9d441c872098dad21d95)) -* **connector-ui:** remove Gemini agent option to prevent chip overflow ([6dacd0f](https://github.com/0xPolygon/polygon-agent-cli/commit/6dacd0f24302924c9feca72b7a284fd4d1c62842)) -* **connector-ui:** replace use cases with x402 catalog services ([231fb3a](https://github.com/0xPolygon/polygon-agent-cli/commit/231fb3a2e7f675401f9bca93ccba1fd16c7f2ca7)) -* **connector-ui:** v2 session flow — relay encryption + 6-digit code display ([b4ac674](https://github.com/0xPolygon/polygon-agent-cli/commit/b4ac674b13c1965bfe48517b812333ff5b4c5289)) -* refactor skills into sub-skill files by use-case ([d8e1f7b](https://github.com/0xPolygon/polygon-agent-cli/commit/d8e1f7b0203f39b4a631b9ac90629e2b801ced92)) -* **skills:** add DeFi sub-skill with swap, bridge, deposit, and vault whitelist ([2da3222](https://github.com/0xPolygon/polygon-agent-cli/commit/2da3222506ba1dfa69f32dc0091817084818d586)) -* **skills:** add x402 Bazaar services section with call instructions ([0f73484](https://github.com/0xPolygon/polygon-agent-cli/commit/0f7348467f97fe48018a8a5bb284d5edbfd10807)) -* **skills:** add yield vault whitelist and fix x402 Bazaar methods to POST ([dc17591](https://github.com/0xPolygon/polygon-agent-cli/commit/dc17591217136d62a0d40ace8ea0a17c910a733e)) -* **ui,skills:** replace code review use case with lead scoring ([73b9283](https://github.com/0xPolygon/polygon-agent-cli/commit/73b92835379f641c81ac5f4b5765449d19e91523)) - - - - - -# [1.3.0](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.0.2...@polygonlabs/agent-connector-ui@1.3.0) (2026-04-14) - - -### Bug Fixes - -* address code review issues — persist cliSk, raise payload limit, validate inputs, cleanup ([f38d2f2](https://github.com/0xPolygon/polygon-agent-cli/commit/f38d2f2afc59122655e46274e201016c0f4240f2)) -* **connector-ui:** add @cloudflare/workers-types for relay DO type resolution ([5e9a070](https://github.com/0xPolygon/polygon-agent-cli/commit/5e9a070b8141687bbc3a95b813b32d7af7b4ad89)) -* **connector-ui:** add quotes around claude command argument and lowercase prefix ([0cfc441](https://github.com/0xPolygon/polygon-agent-cli/commit/0cfc44195e4a1b737be7544f7284632b74ed8f32)) -* **connector-ui:** add SESSION_RELAY DO bindings to staging and production envs ([16fe31e](https://github.com/0xPolygon/polygon-agent-cli/commit/16fe31ef82972ba7840c2881fc71eb5ee5a0fbe2)) -* **connector-ui:** align subtext color to [#6](https://github.com/0xPolygon/polygon-agent-cli/issues/6)b7280 across landing and code screens ([29f7336](https://github.com/0xPolygon/polygon-agent-cli/commit/29f733651f8eb4c5986ad94ffcdcff22d2b38ba0)), closes [#6b7280](https://github.com/0xPolygon/polygon-agent-cli/issues/6b7280) -* **connector-ui:** extend session deadline to 6 months ([cb843b0](https://github.com/0xPolygon/polygon-agent-cli/commit/cb843b05512d326e241cbaab25a93dffb5a94364)) -* **connector-ui:** fix logo to top of screen on all flow screens ([4316ae8](https://github.com/0xPolygon/polygon-agent-cli/commit/4316ae875116dd04af9cd52454179185a6bd8efe)) -* **connector-ui:** fixed centered logo+badge on screens 1-3, onchain spelling ([e687bce](https://github.com/0xPolygon/polygon-agent-cli/commit/e687bce7fd9df1f3540b571da8ce18acc57da57a)) -* **connector-ui:** preserve implicit session metadata, remove tweetnacl, add rid validation ([ca4c4aa](https://github.com/0xPolygon/polygon-agent-cli/commit/ca4c4aa7ce972639e80b3fe4c8cc6abd01db3df1)) -* **connector-ui:** relay init error check, rid validation, re-init guard, payload size limit ([509b34f](https://github.com/0xPolygon/polygon-agent-cli/commit/509b34f593478b3b8e4f4c1cdb02ca355e55379c)) -* **connector-ui:** remove dollar sign from terminal prefix display ([da70d5f](https://github.com/0xPolygon/polygon-agent-cli/commit/da70d5ffbdbb099d873751e87c046611b39189ce)) -* **connector-ui:** remove dollar sign prefix from copied commands ([d8bb2e1](https://github.com/0xPolygon/polygon-agent-cli/commit/d8bb2e1e290f2f57bdc848c894f4dd2be512d5f2)) -* **connector-ui:** remove services list card from dashboard ([be3ee92](https://github.com/0xPolygon/polygon-agent-cli/commit/be3ee92ff1ee42d00cc97d0fdb4b7e45a26bd555)) -* **connector-ui:** restore >_ agent mono badge on all screens ([d753dd7](https://github.com/0xPolygon/polygon-agent-cli/commit/d753dd72e3c866040f618c8a0262e331681ea9b7)) -* **relay:** include code_hash_hex in retrieve response for CLI decryption ([0b713b8](https://github.com/0xPolygon/polygon-agent-cli/commit/0b713b8f380b2f928a0575cc7f2c311177d61d8a)) -* **skills:** quote SKILL.md description to fix YAML colon parse error ([79e1f65](https://github.com/0xPolygon/polygon-agent-cli/commit/79e1f6542f4faed33f8aa4b4db6aa79dc99902db)) -* **skills:** update x402 Bazaar endpoints to use POST, update Twitter prompt ([cee084d](https://github.com/0xPolygon/polygon-agent-cli/commit/cee084dc1bdc5dbfffca6209a8734679c8741e82)) -* **ui:** shorten lead scoring display text, fix duplicate Target icon ([dd3c976](https://github.com/0xPolygon/polygon-agent-cli/commit/dd3c9761878bbabc377baa7e23a253f484fa000a)) -* **x402-pay:** align payment_details handler with x402 Bazaar integration guide ([c3a751e](https://github.com/0xPolygon/polygon-agent-cli/commit/c3a751e1689b6f1dfc3155b30e13de19ec4ca686)) -* **x402-pay:** implement EIP-3009 facilitator path for Polygon payment_details ([42d4d05](https://github.com/0xPolygon/polygon-agent-cli/commit/42d4d05bebe059e7c0ab617f12e88f2411ee0e15)) - - -### Features - -* **cli:** ink UI redesign and DX improvements ([8ad6596](https://github.com/0xPolygon/polygon-agent-cli/commit/8ad6596448b75590d699c1bcf3fa332c73750b7f)) -* **connector-ui:** add Durable Object relay API + upgrade worker routing ([77a093c](https://github.com/0xPolygon/polygon-agent-cli/commit/77a093cbad4e136fd9ada94da8a667b5ff08a26a)) -* **connector-ui:** add Openclaw and Hermes agent options ([e18b076](https://github.com/0xPolygon/polygon-agent-cli/commit/e18b076071ead7223d49732c0202e03f7456a94b)) -* **connector-ui:** apply OMSX Figma design system to all screens ([154afbd](https://github.com/0xPolygon/polygon-agent-cli/commit/154afbd28b818add730edc6d3879548b3e5a3743)), closes [#141635](https://github.com/0xPolygon/polygon-agent-cli/issues/141635) [#64708](https://github.com/0xPolygon/polygon-agent-cli/issues/64708) [#c8cfe1](https://github.com/0xPolygon/polygon-agent-cli/issues/c8cfe1) [#929](https://github.com/0xPolygon/polygon-agent-cli/issues/929) [#141635](https://github.com/0xPolygon/polygon-agent-cli/issues/141635) [#7c3](https://github.com/0xPolygon/polygon-agent-cli/issues/7c3) [#f5f6](https://github.com/0xPolygon/polygon-agent-cli/issues/f5f6) [#929](https://github.com/0xPolygon/polygon-agent-cli/issues/929) -* **connector-ui:** enable Mesh onramp in production for TrailsWidget ([93e562b](https://github.com/0xPolygon/polygon-agent-cli/commit/93e562b70c136e5f9bdeb5786df09b63798778c0)) -* **connector-ui:** redesign — light theme, code display, funding flow ([63b2fcd](https://github.com/0xPolygon/polygon-agent-cli/commit/63b2fcdf7cb46b44d76e9d441c872098dad21d95)) -* **connector-ui:** remove Gemini agent option to prevent chip overflow ([6dacd0f](https://github.com/0xPolygon/polygon-agent-cli/commit/6dacd0f24302924c9feca72b7a284fd4d1c62842)) -* **connector-ui:** replace use cases with x402 catalog services ([231fb3a](https://github.com/0xPolygon/polygon-agent-cli/commit/231fb3a2e7f675401f9bca93ccba1fd16c7f2ca7)) -* **connector-ui:** v2 session flow — relay encryption + 6-digit code display ([b4ac674](https://github.com/0xPolygon/polygon-agent-cli/commit/b4ac674b13c1965bfe48517b812333ff5b4c5289)) -* refactor skills into sub-skill files by use-case ([d8e1f7b](https://github.com/0xPolygon/polygon-agent-cli/commit/d8e1f7b0203f39b4a631b9ac90629e2b801ced92)) -* **skills:** add DeFi sub-skill with swap, bridge, deposit, and vault whitelist ([2da3222](https://github.com/0xPolygon/polygon-agent-cli/commit/2da3222506ba1dfa69f32dc0091817084818d586)) -* **skills:** add x402 Bazaar services section with call instructions ([0f73484](https://github.com/0xPolygon/polygon-agent-cli/commit/0f7348467f97fe48018a8a5bb284d5edbfd10807)) -* **skills:** add yield vault whitelist and fix x402 Bazaar methods to POST ([dc17591](https://github.com/0xPolygon/polygon-agent-cli/commit/dc17591217136d62a0d40ace8ea0a17c910a733e)) -* **ui,skills:** replace code review use case with lead scoring ([73b9283](https://github.com/0xPolygon/polygon-agent-cli/commit/73b92835379f641c81ac5f4b5765449d19e91523)) - - - - - -# [1.2.0](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.0.2...@polygonlabs/agent-connector-ui@1.2.0) (2026-04-14) - - -### Bug Fixes - -* address code review issues — persist cliSk, raise payload limit, validate inputs, cleanup ([f38d2f2](https://github.com/0xPolygon/polygon-agent-cli/commit/f38d2f2afc59122655e46274e201016c0f4240f2)) -* **connector-ui:** add @cloudflare/workers-types for relay DO type resolution ([5e9a070](https://github.com/0xPolygon/polygon-agent-cli/commit/5e9a070b8141687bbc3a95b813b32d7af7b4ad89)) -* **connector-ui:** add quotes around claude command argument and lowercase prefix ([0cfc441](https://github.com/0xPolygon/polygon-agent-cli/commit/0cfc44195e4a1b737be7544f7284632b74ed8f32)) -* **connector-ui:** add SESSION_RELAY DO bindings to staging and production envs ([16fe31e](https://github.com/0xPolygon/polygon-agent-cli/commit/16fe31ef82972ba7840c2881fc71eb5ee5a0fbe2)) -* **connector-ui:** align subtext color to [#6](https://github.com/0xPolygon/polygon-agent-cli/issues/6)b7280 across landing and code screens ([29f7336](https://github.com/0xPolygon/polygon-agent-cli/commit/29f733651f8eb4c5986ad94ffcdcff22d2b38ba0)), closes [#6b7280](https://github.com/0xPolygon/polygon-agent-cli/issues/6b7280) -* **connector-ui:** extend session deadline to 6 months ([cb843b0](https://github.com/0xPolygon/polygon-agent-cli/commit/cb843b05512d326e241cbaab25a93dffb5a94364)) -* **connector-ui:** fix logo to top of screen on all flow screens ([4316ae8](https://github.com/0xPolygon/polygon-agent-cli/commit/4316ae875116dd04af9cd52454179185a6bd8efe)) -* **connector-ui:** fixed centered logo+badge on screens 1-3, onchain spelling ([e687bce](https://github.com/0xPolygon/polygon-agent-cli/commit/e687bce7fd9df1f3540b571da8ce18acc57da57a)) -* **connector-ui:** preserve implicit session metadata, remove tweetnacl, add rid validation ([ca4c4aa](https://github.com/0xPolygon/polygon-agent-cli/commit/ca4c4aa7ce972639e80b3fe4c8cc6abd01db3df1)) -* **connector-ui:** relay init error check, rid validation, re-init guard, payload size limit ([509b34f](https://github.com/0xPolygon/polygon-agent-cli/commit/509b34f593478b3b8e4f4c1cdb02ca355e55379c)) -* **connector-ui:** remove dollar sign from terminal prefix display ([da70d5f](https://github.com/0xPolygon/polygon-agent-cli/commit/da70d5ffbdbb099d873751e87c046611b39189ce)) -* **connector-ui:** remove dollar sign prefix from copied commands ([d8bb2e1](https://github.com/0xPolygon/polygon-agent-cli/commit/d8bb2e1e290f2f57bdc848c894f4dd2be512d5f2)) -* **connector-ui:** remove services list card from dashboard ([be3ee92](https://github.com/0xPolygon/polygon-agent-cli/commit/be3ee92ff1ee42d00cc97d0fdb4b7e45a26bd555)) -* **connector-ui:** restore >_ agent mono badge on all screens ([d753dd7](https://github.com/0xPolygon/polygon-agent-cli/commit/d753dd72e3c866040f618c8a0262e331681ea9b7)) -* **relay:** include code_hash_hex in retrieve response for CLI decryption ([0b713b8](https://github.com/0xPolygon/polygon-agent-cli/commit/0b713b8f380b2f928a0575cc7f2c311177d61d8a)) -* **skills:** quote SKILL.md description to fix YAML colon parse error ([79e1f65](https://github.com/0xPolygon/polygon-agent-cli/commit/79e1f6542f4faed33f8aa4b4db6aa79dc99902db)) -* **skills:** update x402 Bazaar endpoints to use POST, update Twitter prompt ([cee084d](https://github.com/0xPolygon/polygon-agent-cli/commit/cee084dc1bdc5dbfffca6209a8734679c8741e82)) -* **ui:** shorten lead scoring display text, fix duplicate Target icon ([dd3c976](https://github.com/0xPolygon/polygon-agent-cli/commit/dd3c9761878bbabc377baa7e23a253f484fa000a)) -* **x402-pay:** align payment_details handler with x402 Bazaar integration guide ([c3a751e](https://github.com/0xPolygon/polygon-agent-cli/commit/c3a751e1689b6f1dfc3155b30e13de19ec4ca686)) -* **x402-pay:** implement EIP-3009 facilitator path for Polygon payment_details ([42d4d05](https://github.com/0xPolygon/polygon-agent-cli/commit/42d4d05bebe059e7c0ab617f12e88f2411ee0e15)) - - -### Features - -* **cli:** ink UI redesign and DX improvements ([8ad6596](https://github.com/0xPolygon/polygon-agent-cli/commit/8ad6596448b75590d699c1bcf3fa332c73750b7f)) -* **connector-ui:** add Durable Object relay API + upgrade worker routing ([77a093c](https://github.com/0xPolygon/polygon-agent-cli/commit/77a093cbad4e136fd9ada94da8a667b5ff08a26a)) -* **connector-ui:** add Openclaw and Hermes agent options ([e18b076](https://github.com/0xPolygon/polygon-agent-cli/commit/e18b076071ead7223d49732c0202e03f7456a94b)) -* **connector-ui:** apply OMSX Figma design system to all screens ([154afbd](https://github.com/0xPolygon/polygon-agent-cli/commit/154afbd28b818add730edc6d3879548b3e5a3743)), closes [#141635](https://github.com/0xPolygon/polygon-agent-cli/issues/141635) [#64708](https://github.com/0xPolygon/polygon-agent-cli/issues/64708) [#c8cfe1](https://github.com/0xPolygon/polygon-agent-cli/issues/c8cfe1) [#929](https://github.com/0xPolygon/polygon-agent-cli/issues/929) [#141635](https://github.com/0xPolygon/polygon-agent-cli/issues/141635) [#7c3](https://github.com/0xPolygon/polygon-agent-cli/issues/7c3) [#f5f6](https://github.com/0xPolygon/polygon-agent-cli/issues/f5f6) [#929](https://github.com/0xPolygon/polygon-agent-cli/issues/929) -* **connector-ui:** enable Mesh onramp in production for TrailsWidget ([93e562b](https://github.com/0xPolygon/polygon-agent-cli/commit/93e562b70c136e5f9bdeb5786df09b63798778c0)) -* **connector-ui:** redesign — light theme, code display, funding flow ([63b2fcd](https://github.com/0xPolygon/polygon-agent-cli/commit/63b2fcdf7cb46b44d76e9d441c872098dad21d95)) -* **connector-ui:** remove Gemini agent option to prevent chip overflow ([6dacd0f](https://github.com/0xPolygon/polygon-agent-cli/commit/6dacd0f24302924c9feca72b7a284fd4d1c62842)) -* **connector-ui:** replace use cases with x402 catalog services ([231fb3a](https://github.com/0xPolygon/polygon-agent-cli/commit/231fb3a2e7f675401f9bca93ccba1fd16c7f2ca7)) -* **connector-ui:** v2 session flow — relay encryption + 6-digit code display ([b4ac674](https://github.com/0xPolygon/polygon-agent-cli/commit/b4ac674b13c1965bfe48517b812333ff5b4c5289)) -* refactor skills into sub-skill files by use-case ([d8e1f7b](https://github.com/0xPolygon/polygon-agent-cli/commit/d8e1f7b0203f39b4a631b9ac90629e2b801ced92)) -* **skills:** add DeFi sub-skill with swap, bridge, deposit, and vault whitelist ([2da3222](https://github.com/0xPolygon/polygon-agent-cli/commit/2da3222506ba1dfa69f32dc0091817084818d586)) -* **skills:** add x402 Bazaar services section with call instructions ([0f73484](https://github.com/0xPolygon/polygon-agent-cli/commit/0f7348467f97fe48018a8a5bb284d5edbfd10807)) -* **skills:** add yield vault whitelist and fix x402 Bazaar methods to POST ([dc17591](https://github.com/0xPolygon/polygon-agent-cli/commit/dc17591217136d62a0d40ace8ea0a17c910a733e)) -* **ui,skills:** replace code review use case with lead scoring ([73b9283](https://github.com/0xPolygon/polygon-agent-cli/commit/73b92835379f641c81ac5f4b5765449d19e91523)) - - - - - -# [1.1.0](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.0.2...@polygonlabs/agent-connector-ui@1.1.0) (2026-04-14) - - -### Bug Fixes - -* address code review issues — persist cliSk, raise payload limit, validate inputs, cleanup ([f38d2f2](https://github.com/0xPolygon/polygon-agent-cli/commit/f38d2f2afc59122655e46274e201016c0f4240f2)) -* **connector-ui:** add @cloudflare/workers-types for relay DO type resolution ([5e9a070](https://github.com/0xPolygon/polygon-agent-cli/commit/5e9a070b8141687bbc3a95b813b32d7af7b4ad89)) -* **connector-ui:** add quotes around claude command argument and lowercase prefix ([0cfc441](https://github.com/0xPolygon/polygon-agent-cli/commit/0cfc44195e4a1b737be7544f7284632b74ed8f32)) -* **connector-ui:** add SESSION_RELAY DO bindings to staging and production envs ([16fe31e](https://github.com/0xPolygon/polygon-agent-cli/commit/16fe31ef82972ba7840c2881fc71eb5ee5a0fbe2)) -* **connector-ui:** align subtext color to [#6](https://github.com/0xPolygon/polygon-agent-cli/issues/6)b7280 across landing and code screens ([29f7336](https://github.com/0xPolygon/polygon-agent-cli/commit/29f733651f8eb4c5986ad94ffcdcff22d2b38ba0)), closes [#6b7280](https://github.com/0xPolygon/polygon-agent-cli/issues/6b7280) -* **connector-ui:** extend session deadline to 6 months ([cb843b0](https://github.com/0xPolygon/polygon-agent-cli/commit/cb843b05512d326e241cbaab25a93dffb5a94364)) -* **connector-ui:** fix logo to top of screen on all flow screens ([4316ae8](https://github.com/0xPolygon/polygon-agent-cli/commit/4316ae875116dd04af9cd52454179185a6bd8efe)) -* **connector-ui:** fixed centered logo+badge on screens 1-3, onchain spelling ([e687bce](https://github.com/0xPolygon/polygon-agent-cli/commit/e687bce7fd9df1f3540b571da8ce18acc57da57a)) -* **connector-ui:** preserve implicit session metadata, remove tweetnacl, add rid validation ([ca4c4aa](https://github.com/0xPolygon/polygon-agent-cli/commit/ca4c4aa7ce972639e80b3fe4c8cc6abd01db3df1)) -* **connector-ui:** relay init error check, rid validation, re-init guard, payload size limit ([509b34f](https://github.com/0xPolygon/polygon-agent-cli/commit/509b34f593478b3b8e4f4c1cdb02ca355e55379c)) -* **connector-ui:** remove dollar sign from terminal prefix display ([da70d5f](https://github.com/0xPolygon/polygon-agent-cli/commit/da70d5ffbdbb099d873751e87c046611b39189ce)) -* **connector-ui:** remove dollar sign prefix from copied commands ([d8bb2e1](https://github.com/0xPolygon/polygon-agent-cli/commit/d8bb2e1e290f2f57bdc848c894f4dd2be512d5f2)) -* **connector-ui:** remove services list card from dashboard ([be3ee92](https://github.com/0xPolygon/polygon-agent-cli/commit/be3ee92ff1ee42d00cc97d0fdb4b7e45a26bd555)) -* **connector-ui:** restore >_ agent mono badge on all screens ([d753dd7](https://github.com/0xPolygon/polygon-agent-cli/commit/d753dd72e3c866040f618c8a0262e331681ea9b7)) -* **relay:** include code_hash_hex in retrieve response for CLI decryption ([0b713b8](https://github.com/0xPolygon/polygon-agent-cli/commit/0b713b8f380b2f928a0575cc7f2c311177d61d8a)) -* **skills:** quote SKILL.md description to fix YAML colon parse error ([79e1f65](https://github.com/0xPolygon/polygon-agent-cli/commit/79e1f6542f4faed33f8aa4b4db6aa79dc99902db)) -* **skills:** update x402 Bazaar endpoints to use POST, update Twitter prompt ([cee084d](https://github.com/0xPolygon/polygon-agent-cli/commit/cee084dc1bdc5dbfffca6209a8734679c8741e82)) -* **ui:** shorten lead scoring display text, fix duplicate Target icon ([dd3c976](https://github.com/0xPolygon/polygon-agent-cli/commit/dd3c9761878bbabc377baa7e23a253f484fa000a)) -* **x402-pay:** align payment_details handler with x402 Bazaar integration guide ([c3a751e](https://github.com/0xPolygon/polygon-agent-cli/commit/c3a751e1689b6f1dfc3155b30e13de19ec4ca686)) -* **x402-pay:** implement EIP-3009 facilitator path for Polygon payment_details ([42d4d05](https://github.com/0xPolygon/polygon-agent-cli/commit/42d4d05bebe059e7c0ab617f12e88f2411ee0e15)) - - -### Features - -* **cli:** ink UI redesign and DX improvements ([8ad6596](https://github.com/0xPolygon/polygon-agent-cli/commit/8ad6596448b75590d699c1bcf3fa332c73750b7f)) -* **connector-ui:** add Durable Object relay API + upgrade worker routing ([77a093c](https://github.com/0xPolygon/polygon-agent-cli/commit/77a093cbad4e136fd9ada94da8a667b5ff08a26a)) -* **connector-ui:** add Openclaw and Hermes agent options ([e18b076](https://github.com/0xPolygon/polygon-agent-cli/commit/e18b076071ead7223d49732c0202e03f7456a94b)) -* **connector-ui:** apply OMSX Figma design system to all screens ([154afbd](https://github.com/0xPolygon/polygon-agent-cli/commit/154afbd28b818add730edc6d3879548b3e5a3743)), closes [#141635](https://github.com/0xPolygon/polygon-agent-cli/issues/141635) [#64708](https://github.com/0xPolygon/polygon-agent-cli/issues/64708) [#c8cfe1](https://github.com/0xPolygon/polygon-agent-cli/issues/c8cfe1) [#929](https://github.com/0xPolygon/polygon-agent-cli/issues/929) [#141635](https://github.com/0xPolygon/polygon-agent-cli/issues/141635) [#7c3](https://github.com/0xPolygon/polygon-agent-cli/issues/7c3) [#f5f6](https://github.com/0xPolygon/polygon-agent-cli/issues/f5f6) [#929](https://github.com/0xPolygon/polygon-agent-cli/issues/929) -* **connector-ui:** enable Mesh onramp in production for TrailsWidget ([93e562b](https://github.com/0xPolygon/polygon-agent-cli/commit/93e562b70c136e5f9bdeb5786df09b63798778c0)) -* **connector-ui:** redesign — light theme, code display, funding flow ([63b2fcd](https://github.com/0xPolygon/polygon-agent-cli/commit/63b2fcdf7cb46b44d76e9d441c872098dad21d95)) -* **connector-ui:** remove Gemini agent option to prevent chip overflow ([6dacd0f](https://github.com/0xPolygon/polygon-agent-cli/commit/6dacd0f24302924c9feca72b7a284fd4d1c62842)) -* **connector-ui:** replace use cases with x402 catalog services ([231fb3a](https://github.com/0xPolygon/polygon-agent-cli/commit/231fb3a2e7f675401f9bca93ccba1fd16c7f2ca7)) -* **connector-ui:** v2 session flow — relay encryption + 6-digit code display ([b4ac674](https://github.com/0xPolygon/polygon-agent-cli/commit/b4ac674b13c1965bfe48517b812333ff5b4c5289)) -* refactor skills into sub-skill files by use-case ([d8e1f7b](https://github.com/0xPolygon/polygon-agent-cli/commit/d8e1f7b0203f39b4a631b9ac90629e2b801ced92)) -* **skills:** add DeFi sub-skill with swap, bridge, deposit, and vault whitelist ([2da3222](https://github.com/0xPolygon/polygon-agent-cli/commit/2da3222506ba1dfa69f32dc0091817084818d586)) -* **skills:** add x402 Bazaar services section with call instructions ([0f73484](https://github.com/0xPolygon/polygon-agent-cli/commit/0f7348467f97fe48018a8a5bb284d5edbfd10807)) -* **skills:** add yield vault whitelist and fix x402 Bazaar methods to POST ([dc17591](https://github.com/0xPolygon/polygon-agent-cli/commit/dc17591217136d62a0d40ace8ea0a17c910a733e)) -* **ui,skills:** replace code review use case with lead scoring ([73b9283](https://github.com/0xPolygon/polygon-agent-cli/commit/73b92835379f641c81ac5f4b5765449d19e91523)) - - - - - -## [1.0.2](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.0.1...@polygonlabs/agent-connector-ui@1.0.2) (2026-03-05) - - -### Bug Fixes - -* **publish:** add repository field to package.json files ([b037364](https://github.com/0xPolygon/polygon-agent-cli/commit/b037364323343900a041e16e4b8f7ff92345d95e)) - - - - - -## [1.0.1](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-connector-ui@1.0.0...@polygonlabs/agent-connector-ui@1.0.1) (2026-03-04) - -**Note:** Version bump only for package @polygonlabs/agent-connector-ui diff --git a/packages/connector-ui/README.md b/packages/connector-ui/README.md deleted file mode 100644 index bcd7c3c..0000000 --- a/packages/connector-ui/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# Polygon Agent CLI - Wallet Connector - -Session-based wallet connector for Polygon Agent CLI agents. Creates secure encrypted wallet sessions for CLI and autonomous agent operations. - -## Features - -- **Explicit Sessions**: Creates session keys with granular permissions for token operations -- **Encrypted Export**: Encrypts session credentials using NaCl sealed-box for secure CLI/agent ingest -- **Token Limits**: Supports native (POL) and ERC20 spending limits (USDC, USDT, custom tokens) -- **Balance Display**: Shows wallet balances after connection -- **Callback Support**: Automatic callback delivery to the CLI (default mode) - -## Quickstart - -Copy `.env.example` to `.env` and fill with your project information: - -```bash -cp .env.example .env -``` - -Install and run: - -```bash -pnpm install && pnpm dev -``` - -The app will start on `localhost:4444` - -To provide your own keys from [Sequence Builder](https://sequence.build/), edit the `.env` file with your `VITE_PROJECT_ACCESS_KEY`. - -## Usage with Polygon Agent CLI - -### Auto-Wait (Default — zero copy/paste) - -```bash -polygon-agent wallet create -``` - -The CLI starts a local HTTP server and outputs a URL. Open the URL in browser, approve the session — the connector UI POSTs the encrypted session back automatically. - -### Manual Flow - -1. Run `polygon-agent wallet create --no-wait` to generate a session link -2. Open the link in browser -3. Click "Connect wallet" and approve in Ecosystem Wallet -4. Copy the encrypted blob -5. Run `polygon-agent wallet import --ciphertext @/tmp/session.txt` diff --git a/packages/connector-ui/public/vite.svg b/packages/connector-ui/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/packages/connector-ui/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/connector-ui/src/App.tsx b/packages/connector-ui/src/App.tsx deleted file mode 100644 index a7300de..0000000 --- a/packages/connector-ui/src/App.tsx +++ /dev/null @@ -1,858 +0,0 @@ -import type { ElementType } from 'react'; - -import './App.css'; - -import { - Wallet, - Copy, - AlertCircle, - Plus, - Twitter, - BarChart2, - Target, - ArrowLeftRight, - TrendingUp -} from 'lucide-react'; -import { Hex, Signature } from 'ox'; -import { useEffect, useMemo, useState } from 'react'; - -import type { SessionPayload } from '@polygonlabs/agent-shared'; - -import { - DappClient, - TransportMode, - WebStorage, - jsonReplacers, - Utils, - Permission -} from '@0xsequence/dapp-client'; -import { encryptSession } from '@polygonlabs/agent-shared'; - -import { CodeDisplay } from './components/CodeDisplay.js'; -import { FundingScreen } from './components/FundingScreen.js'; -import { dappOrigin, projectAccessKey, walletUrl, relayerUrl, nodesUrl } from './config'; -import { resolveChainId, fetchTotalUsdBalance } from './indexer'; -import { resolveErc20Symbol } from './tokenDirectory'; - -async function deleteIndexedDb(dbName: string): Promise { - await new Promise((resolve) => { - const req = indexedDB.deleteDatabase(dbName); - req.onsuccess = () => resolve(); - req.onerror = () => resolve(); - req.onblocked = () => resolve(); - }); -} - -async function resetLocalSessionStateForNewRid(rid: string): Promise { - if (!rid) return false; - const key = 'moltbot.lastRid'; - const lastRid = window.localStorage.getItem(key); - if (lastRid === rid) return false; - window.localStorage.setItem(key, rid); - try { - sessionStorage.clear(); - } catch {} - await deleteIndexedDb('SequenceDappStorage'); - return true; -} - -// --- Static background: use-cases panel --- - -// v2 -const SKILL_URL = 'https://agentconnect.polygon.technology/SKILL.md'; - -const AGENTS: { - id: string; - label: string; - color: string; - terminalPrefix: string; - buildCommand: (display: string) => string; -}[] = [ - { - id: 'claude', - label: 'Claude', - color: '#D97706', - terminalPrefix: 'claude', - buildCommand: (display) => `claude "Read ${SKILL_URL} and ${display}"` - }, - { - id: 'codex', - label: 'Codex', - color: '#10A37F', - terminalPrefix: 'codex', - buildCommand: (display) => `codex "Read ${SKILL_URL} and ${display}"` - }, - { - id: 'openclaw', - label: 'Openclaw', - color: '#8B5CF6', - terminalPrefix: 'clawhub', - buildCommand: (display) => `npx clawhub@latest run "Read ${SKILL_URL} and ${display}"` - }, - { - id: 'hermes', - label: 'Hermes', - color: '#EC4899', - terminalPrefix: 'hermes', - buildCommand: (display) => `hermes "Read ${SKILL_URL} and ${display}"` - } -]; - -const USE_CASES: { label: string; display: string; icon: ElementType }[] = [ - { - label: 'Read Twitter/X profiles & tweets', - display: - 'Use x402 to read a Twitter/X profile and recent tweets. Get follower counts, recent tweets, and engagement metrics.', - icon: Twitter - }, - { - label: 'Score a sales lead', - display: - 'Score any company domain as a B2B sales lead. Get a 0–100 score and A–F grade from various signals.', - icon: BarChart2 - }, - { - label: 'Make a bet on polymarket', - display: 'Make a bet on a Polymarket market. Get the latest market prices and outcomes.', - icon: Target - }, - { - label: 'Bridge assets cross-chain', - display: - 'Bridge some USDC from Polygon to Base using the cheapest available route. Confirm the arrival and report the final balance on both chains.', - icon: ArrowLeftRight - }, - { - label: 'Automate yield strategies', - display: - 'Deposit USDC into the highest-yield active lending vault on Polygon and report the APY and pool address. Then set up a daily cron job to automatically re-evaluate and deposit into the best vault each morning.', - icon: TrendingUp - } -]; - -// --- Main App --- - -function App() { - const params = useMemo(() => new URLSearchParams(window.location.search), []); - const rid = params.get('rid') || ''; - const walletName = params.get('wallet') || ''; - - const chainId = useMemo(() => resolveChainId(params), [params]); - - const [error, setError] = useState(''); - const [walletAddress, setWalletAddress] = useState(''); - const [cliPkHex, setCliPkHex] = useState(''); - const [sessionCode, setSessionCode] = useState(''); - const [showFunding, setShowFunding] = useState(false); - const [showDashboard, setShowDashboard] = useState(false); - const [feeTokens, setFeeTokens] = useState(null); - const [selectedUseCase, setSelectedUseCase] = useState(0); - const [selectedAgent, setSelectedAgent] = useState('claude'); - const [copied, setCopied] = useState(false); - const [connecting, setConnecting] = useState(false); - const [totalUsd, setTotalUsd] = useState(null); - - // Reset local session state on new rid - useEffect(() => { - void (async () => { - const didReset = await resetLocalSessionStateForNewRid(rid); - if (didReset) window.location.reload(); - })(); - }, [rid]); - - // Fetch CLI public key from relay - useEffect(() => { - if (!rid) return; - if (!/^[a-z0-9]{8}$/.test(rid)) { - setError('Invalid session link. Please generate a new connection URL.'); - return; - } - fetch(`/api/relay/request/${rid}`) - .then((r) => { - if (!r.ok) throw new Error(`Relay returned ${r.status}`); - return r.json() as Promise<{ cli_pk_hex: string }>; - }) - .then(({ cli_pk_hex }) => { - if (!/^[0-9a-f]{64}$/.test(cli_pk_hex)) { - throw new Error('Invalid cli_pk_hex format received from relay'); - } - setCliPkHex(cli_pk_hex); - }) - .catch((e: any) => setError(`Failed to load session key: ${e?.message || String(e)}`)); - }, [rid]); - - // Fetch USD portfolio balance when wallet address is first known - useEffect(() => { - if (!walletAddress) return; - setTotalUsd(null); - fetchTotalUsdBalance(walletAddress, chainId) - .then(setTotalUsd) - .catch(() => setTotalUsd(null)); - }, [walletAddress, chainId]); - - // Poll relay status after code shown — auto-transition to funding when CLI retrieves payload - useEffect(() => { - if (!sessionCode || !rid || showFunding) return; - let active = true; - const poll = async () => { - try { - const res = await fetch(`/api/relay/status/${rid}`); - if (res.status === 404 && active) { - setShowFunding(true); - } - } catch { - // network error — keep polling - } - }; - const id = setInterval(poll, 2000); - return () => { - active = false; - clearInterval(id); - }; - }, [sessionCode, rid, showFunding]); - - const dappClient = useMemo(() => { - return new DappClient(walletUrl, dappOrigin, projectAccessKey, { - transportMode: TransportMode.POPUP, - relayerUrl, - nodesUrl, - sequenceStorage: new WebStorage() - }); - }, []); - - useEffect(() => { - void (async () => { - try { - await dappClient.initialize(); - try { - setFeeTokens(await dappClient.getFeeTokens(chainId)); - } catch { - setFeeTokens(null); - } - } catch (e: any) { - setError(e?.message || String(e)); - } - })(); - }, [dappClient]); - - const connect = async () => { - void feeTokens; - setError(''); - setSessionCode(''); - setConnecting(true); - - if (!rid || !walletName) { - setError('Invalid link. Missing rid or wallet.'); - return; - } - if (!cliPkHex) { - setError('Session key not loaded yet. Please wait or refresh.'); - return; - } - - try { - const VALUE_FORWARDER = '0xABAAd93EeE2a569cF0632f39B10A9f5D734777ca'; - const USDC = (await resolveErc20Symbol(chainId, 'USDC'))?.address; - const USDT = (await resolveErc20Symbol(chainId, 'USDT'))?.address; - const basePermissions: any[] = [{ target: VALUE_FORWARDER, rules: [] }]; - const searchParams = new URLSearchParams(window.location.search); - const erc20 = searchParams.get('erc20'); - const erc20To = searchParams.get('erc20To'); - const erc20Amount = searchParams.get('erc20Amount'); - const oneOffErc20Permissions: any[] = - erc20 && erc20To && erc20Amount - ? (() => { - const tokenAddr = erc20.toLowerCase() === 'usdc' ? USDC : erc20; - const decimals = erc20.toLowerCase() === 'usdc' ? 6 : 18; - const [i, fRaw = ''] = String(erc20Amount).split('.'); - const f = (fRaw + '0'.repeat(decimals)).slice(0, decimals); - const valueLimit = BigInt(i || '0') * 10n ** BigInt(decimals) + BigInt(f || '0'); - return [ - Utils.PermissionBuilder.for(tokenAddr as any) - .forFunction('function transfer(address to, uint256 value)') - .withUintNParam( - 'value', - valueLimit, - 256, - Permission.ParameterOperation.LESS_THAN_OR_EQUAL, - true - ) - .withAddressParam( - 'to', - erc20To as any, - Permission.ParameterOperation.EQUAL, - false - ) - .build() - ]; - })() - : []; - - const usdcLimit = searchParams.get('usdcLimit'); - const usdtLimit = searchParams.get('usdtLimit'); - const nativeLimit = searchParams.get('nativeLimit') || searchParams.get('polLimit'); - const tokenLimitsRaw = searchParams.get('tokenLimits'); - const USDC_E_POLYGON = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174'; - const openTokenPermissions: any[] = []; - const dynamicTokenPermissions: any[] = []; - if (tokenLimitsRaw) { - const parts = tokenLimitsRaw - .split(',') - .map((s) => s.trim()) - .filter(Boolean); - for (const p of parts) { - const [sym, amt] = p.split(':').map((x) => (x || '').trim()); - if (!sym || !amt) throw new Error(`Invalid tokenLimits entry: ${p}`); - const td = await resolveErc20Symbol(chainId, sym); - if (!td) throw new Error(`${sym} not found for this chain in token-directory`); - dynamicTokenPermissions.push( - Utils.PermissionBuilder.for(td.address as any) - .forFunction('function transfer(address to, uint256 value)') - .withUintNParam( - 'value', - BigInt(Math.floor(parseFloat(amt) * 10 ** td.decimals)), - 256, - Permission.ParameterOperation.LESS_THAN_OR_EQUAL, - true - ) - .build() - ); - } - } - if (usdcLimit) { - if (!USDC) throw new Error('USDC not found for this chain in token-directory'); - const valueLimit = BigInt(parseFloat(usdcLimit) * 1e6); - openTokenPermissions.push( - Utils.PermissionBuilder.for(USDC as any) - .forFunction('function transfer(address to, uint256 value)') - .withUintNParam( - 'value', - valueLimit, - 256, - Permission.ParameterOperation.LESS_THAN_OR_EQUAL, - true - ) - .build() - ); - if (chainId === 137) { - openTokenPermissions.push( - Utils.PermissionBuilder.for(USDC_E_POLYGON as any) - .forFunction('function transfer(address to, uint256 value)') - .withUintNParam( - 'value', - valueLimit, - 256, - Permission.ParameterOperation.LESS_THAN_OR_EQUAL, - true - ) - .build() - ); - } - } - if (usdtLimit) { - if (!USDT) throw new Error('USDT not found for this chain in token-directory'); - openTokenPermissions.push( - Utils.PermissionBuilder.for(USDT as any) - .forFunction('function transfer(address to, uint256 value)') - .withUintNParam( - 'value', - BigInt(parseFloat(usdtLimit) * 1e6), - 256, - Permission.ParameterOperation.LESS_THAN_OR_EQUAL, - true - ) - .build() - ); - } - // Parse user-supplied --contract whitelist first so we can use it to - // filter the auto-injected fee permissions below. Without this, a fee - // token (e.g. USDC) shadows the user's unrestricted entry with a - // transfer-only rule and the Sapient signer rejects approve()/other - // non-transfer calls against that contract. - const contractsRaw = searchParams.get('contracts'); - const whitelistedTargets = new Set( - (contractsRaw ?? '') - .split(',') - .map((s) => s.trim().toLowerCase()) - .filter((s) => /^0x[a-f0-9]{40}$/.test(s)) - ); - - const nativeFeePermission: any[] = []; - const feePermissions: any[] = - (feeTokens as any)?.paymentAddress && Array.isArray((feeTokens as any)?.tokens) - ? ((feeTokens as any).tokens as any[]) - .filter((t) => !!t?.contractAddress) - .filter((t) => !whitelistedTargets.has(String(t.contractAddress).toLowerCase())) - .map((token: any) => { - const decimals = typeof token.decimals === 'number' ? token.decimals : 6; - const valueLimit = - decimals === 18 ? 100000000000000000n : 50n * 10n ** BigInt(decimals); - return Utils.PermissionBuilder.for(token.contractAddress as any) - .forFunction('function transfer(address to, uint256 value)') - .withUintNParam( - 'value', - valueLimit, - 256, - Permission.ParameterOperation.LESS_THAN_OR_EQUAL, - true - ) - .withAddressParam( - 'to', - (feeTokens as any).paymentAddress as any, - Permission.ParameterOperation.EQUAL, - false - ) - .build(); - }) - : []; - - const contractWhitelistPermissions: any[] = Array.from(whitelistedTargets).map((addr) => ({ - target: addr as any, - rules: [] - })); - - const polValueLimit = nativeLimit - ? BigInt(Math.floor(parseFloat(nativeLimit) * 1e18)) - : 2000000000000000000n; - const sessionConfig = { - chainId, - valueLimit: polValueLimit, - deadline: BigInt(Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 183), - permissions: [ - ...basePermissions, - ...oneOffErc20Permissions, - ...openTokenPermissions, - ...dynamicTokenPermissions, - ...nativeFeePermission, - ...feePermissions, - ...contractWhitelistPermissions - ] - }; - - await dappClient.connect(chainId, sessionConfig as any, { includeImplicitSession: true }); - - const addr = await dappClient.getWalletAddress(); - if (!addr) throw new Error('Wallet address not available after connect'); - setWalletAddress(addr); - - const storage = (dappClient as any).sequenceStorage; - const sessions = await storage.getExplicitSessions(); - const explicit = (sessions || []).find( - (s: any) => - String(s.chainId) === String(chainId) && - String(s.walletAddress).toLowerCase() === addr.toLowerCase() - ); - if (!explicit?.pk) throw new Error('Could not locate explicit session pk after connect'); - - const implicit = await storage.getImplicitSession(); - if (!implicit?.pk || !implicit?.attestation || !implicit?.identitySignature) { - throw new Error('Could not locate implicit session material after connect'); - } - - const sigAny: any = implicit.identitySignature; - let identitySignature: string; - if (typeof sigAny === 'string') { - identitySignature = sigAny; - } else if (sigAny instanceof Uint8Array) { - identitySignature = Hex.from(sigAny); - } else if (sigAny && typeof sigAny === 'object') { - identitySignature = typeof sigAny.data === 'string' ? sigAny.data : Signature.toHex(sigAny); - } else { - throw new Error('Unsupported identitySignature type'); - } - - const { Secp256k1, Address: OxAddress, Hex: OxHex } = await import('ox'); - const sessionAddress = OxAddress.fromPublicKey( - Secp256k1.getPublicKey({ privateKey: OxHex.toBytes(explicit.pk) }) - ); - - const sessionPayloadData: SessionPayload = { - version: 1, - wallet_address: addr, - chain_id: chainId, - session_private_key: explicit.pk, - session_address: sessionAddress, - permissions: { - native_limit: polValueLimit.toString(), - erc20_limits: [], - contract_calls: [] - }, - expiry: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 183, - ecosystem_wallet_url: walletUrl, - dapp_origin: dappOrigin, - project_access_key: projectAccessKey, - session_config: JSON.stringify(sessionConfig, jsonReplacers), - implicit_session: { - pk: - typeof implicit.pk === 'string' - ? implicit.pk - : JSON.stringify(implicit.pk, jsonReplacers), - attestation: - typeof implicit.attestation === 'string' - ? implicit.attestation - : JSON.stringify(implicit.attestation, jsonReplacers), - identity_sig: identitySignature, - guard: (implicit as any).guard - ? JSON.stringify((implicit as any).guard, jsonReplacers) - : undefined, - login_method: (implicit as any).loginMethod ?? undefined, - user_email: (implicit as any).userEmail ?? undefined - } - }; - - const { encrypted, code } = encryptSession(sessionPayloadData, cliPkHex, rid); - const relayRes = await fetch(`/api/relay/session/${rid}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(encrypted) - }); - if (!relayRes.ok) throw new Error(`Failed to deliver session to relay (${relayRes.status})`); - - setSessionCode(code); - setConnecting(false); - } catch (e: any) { - console.error(e); - setError(e?.message || String(e)); - setConnecting(false); - } - }; - - const shortAddr = walletAddress - ? `${walletAddress.slice(0, 6)}..${walletAddress.slice(-4)}` - : null; - - // ── Screen 1: Connecting (no wallet yet, or encrypting) ── - if (!walletAddress || (walletAddress && !sessionCode && !showFunding && !showDashboard)) { - const isWaiting = connecting || (walletAddress && !sessionCode); - return ( -
-
- Polygon - - >_ agent - -
-
- {/* Header */} -
-

Connect your agent wallet

-

- Create a secure session to authorize onchain operations -

-
- -
- {isWaiting ? ( -
-
- Waiting for wallet authorization… -
- ) : ( - - )} - - {error && ( -
- -
-

{error}

- -
-
- )} -
- -
- Powered by - Polygon -
-
-
- ); - } - - // ── Screen 2: Code confirm ── - if (sessionCode && !showFunding && !showDashboard) { - return ( -
-
- Polygon - - >_ agent - -
- setShowFunding(true)} - onRegenerate={() => { - setSessionCode(''); - void connect(); - }} - /> -
- ); - } - - // ── Screen 3: Funding ── - if (showFunding && !showDashboard) { - return ( -
-
- Polygon - - >_ agent - -
-
- { - setShowDashboard(true); - setTotalUsd(null); - fetchTotalUsdBalance(walletAddress, chainId) - .then(setTotalUsd) - .catch(() => setTotalUsd(null)); - }} - /> -
-
- ); - } - - // ── Screen 4: Dashboard ── - return ( -
- {/* Nav */} - - -
- {/* Balance row */} -
-
-
- {totalUsd === null ? ( - $— - ) : ( - `$${totalUsd.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` - )} -
-
-
- {walletAddress} -
-
- -
- - {/* Section header */} -
-

Use your wallet with agents

- - - polygon-agent connected - -
- - {/* Use cases + terminal */} -
- {/* Left: use cases */} -
-
- {USE_CASES.map((uc, i) => { - const Icon = uc.icon; - return ( - - ); - })} -
- - - - - See all use cases - -
- - {/* Right: terminal */} -
-
-               a.id === selectedAgent)?.color }}
-              >
-                {AGENTS.find((a) => a.id === selectedAgent)?.terminalPrefix}
-              
-              {' "'}
-              {USE_CASES[selectedUseCase].display}"
-            
-
- {/* Agent selector chips */} -
- Run with - {AGENTS.map((agent) => ( - - ))} -
- -
-
-
- - {/* Learn more */} -

Learn more

-
- {[ - { - title: 'Github', - desc: 'Browse the source code, open issues, and contribute to the Polygon Agent CLI.', - href: 'https://github.com/0xPolygon/polygon-agent-cli' - }, - { - title: 'Docs', - desc: 'Full CLI reference, quickstart guide, and architecture docs to get your agent onchain fast.', - href: 'https://docs.polygon.technology/payment-services/agentic-payments/polygon-agent-cli' - } - ].map((card) => ( - -
- {card.title} - - - -
-

{card.desc}

-
- ))} -
- -
- Powered by Polygon -
-
-
- ); -} - -export { App }; diff --git a/packages/connector-ui/src/assets/react.svg b/packages/connector-ui/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/packages/connector-ui/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/connector-ui/src/components/CodeDisplay.tsx b/packages/connector-ui/src/components/CodeDisplay.tsx deleted file mode 100644 index b7dad17..0000000 --- a/packages/connector-ui/src/components/CodeDisplay.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { Copy, Check, RefreshCw } from 'lucide-react'; -import { useEffect, useState } from 'react'; - -interface CodeDisplayProps { - code: string; - walletAddress: string; - totalUsd: number | null; - onContinue: () => void; - onRegenerate: () => void; -} - -export function CodeDisplay({ code, walletAddress, totalUsd, onRegenerate }: CodeDisplayProps) { - const [copied, setCopied] = useState(false); - const [seconds, setSeconds] = useState(300); // matches relay 5-min TTL - - const displayCode = `${code.slice(0, 3)} - ${code.slice(3)}`; - - const shortAddr = walletAddress ? `${walletAddress.slice(0, 6)}..${walletAddress.slice(-4)}` : ''; - - useEffect(() => { - const id = setInterval(() => setSeconds((s) => Math.max(0, s - 1)), 1000); - return () => clearInterval(id); - }, []); - - const mins = Math.floor(seconds / 60); - const secs = seconds % 60; - const timeStr = `${mins}:${secs.toString().padStart(2, '0')}`; - - function handleCopy() { - navigator.clipboard.writeText(code).catch(() => {}); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } - - return ( -
- {/* Wallet chip header */} -
-
-
-
{shortAddr}
-
- {totalUsd === null - ? '—' - : `$${totalUsd.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`} -
-
-
- - {/* Code section */} -
-

Confirm your code

-

- Enter this code in your terminal or send it to your agent -

- - {/* Code box */} -
- - {displayCode} - - -
- - {/* Expiry + regenerate */} -
- Expires in {timeStr} - · - -
-
- - {/* Footer */} -
- Powered by - Polygon -
-
- ); -} diff --git a/packages/connector-ui/src/config.ts b/packages/connector-ui/src/config.ts deleted file mode 100644 index 237423b..0000000 --- a/packages/connector-ui/src/config.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Configured via VITE_* secrets (per-environment values set in GitHub Environments) -const walletUrlRaw = import.meta.env.VITE_WALLET_URL as string; -// Avoid double slashes in wallet routing (walletUrl should not end with /) -export const walletUrl = walletUrlRaw.replace(/\/+$/, ''); - -// If not explicitly provided, default to the current origin. -export const dappOrigin = - (import.meta.env.VITE_DAPP_ORIGIN as string | undefined) || window.location.origin; - -export const projectAccessKey = import.meta.env.VITE_PROJECT_ACCESS_KEY as string; -export const relayerUrl = (import.meta.env.VITE_RELAYER_URL as string | undefined) || undefined; -export const trailsApiKey = (import.meta.env.VITE_TRAILS_API_KEY as string | undefined) ?? ''; - -// Pass the base gateway URL; the Sequence SDK composes the final URL with the access key. -export const nodesUrl = - (import.meta.env.VITE_NODES_URL as string | undefined) || 'https://nodes.sequence.app/{network}'; diff --git a/packages/connector-ui/src/relay.ts b/packages/connector-ui/src/relay.ts deleted file mode 100644 index e69694d..0000000 --- a/packages/connector-ui/src/relay.ts +++ /dev/null @@ -1,292 +0,0 @@ -import { MAX_CODE_ATTEMPTS, REQUEST_TTL_SECONDS } from '@polygonlabs/agent-shared'; - -/** - * Relay module for v2 session handoff. - * - * Two exports: - * - `SessionRelay` — Cloudflare Durable Object that stores the encrypted session - * payload for one 5-minute window. Internal-only; accessed via `SESSION_RELAY` binding. - * - `handleRelayRequest` — Route dispatcher called from the main Worker for all - * `/api/relay/*` requests from browsers and the CLI. - */ - -// --- Validation helpers --- - -function isHex(s: unknown, len: number): s is string { - return typeof s === 'string' && s.length === len && /^[0-9a-f]+$/.test(s); -} - -function isB64url(s: unknown): s is string { - return typeof s === 'string' && s.length > 0 && /^[A-Za-z0-9_-]+$/.test(s); -} - -/** Constant-time hex string comparison (avoids timing attacks). */ -function constantTimeEqual(a: string, b: string): boolean { - if (a.length !== b.length) return false; - let diff = 0; - for (let i = 0; i < a.length; i++) { - diff |= a.charCodeAt(i) ^ b.charCodeAt(i); - } - return diff === 0; -} - -function cors(response: Response): Response { - const h = new Headers(response.headers); - h.set('Access-Control-Allow-Origin', '*'); - h.set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS'); - h.set('Access-Control-Allow-Headers', 'Content-Type'); - return new Response(response.body, { status: response.status, headers: h }); -} - -function json(data: unknown, status = 200): Response { - return cors(Response.json(data, { status })); -} - -function err(msg: string, status: number): Response { - return cors( - new Response(JSON.stringify({ error: msg }), { - status, - headers: { 'Content-Type': 'application/json' } - }) - ); -} - -// --- Durable Object --- - -export class SessionRelay { - private state: DurableObjectState; - - constructor(state: DurableObjectState) { - this.state = state; - } - - async fetch(request: Request): Promise { - const url = new URL(request.url); - const { method } = request; - - if (method === 'OPTIONS') return cors(new Response(null, { status: 204 })); - - if (method === 'POST' && url.pathname === '/init') return this.handleInit(request); - if (method === 'GET' && url.pathname === '/public-key') return this.handleGetPublicKey(); - if (method === 'POST' && url.pathname === '/session') return this.handlePostSession(request); - if (method === 'GET' && url.pathname === '/status') return this.handleGetStatus(); - if (method === 'POST' && url.pathname === '/retrieve') return this.handleRetrieve(request); - - return err('Not found', 404); - } - - private async handleInit(request: Request): Promise { - let body: unknown; - try { - body = await request.json(); - } catch { - return err('Invalid JSON', 400); - } - const { cli_pk_hex } = body as Record; - if (!isHex(cli_pk_hex, 64)) return err('cli_pk_hex must be 64 hex chars', 400); - - const existing = await this.state.storage.get('status'); - if (existing) return err('Already initialized', 409); - - await this.state.storage.put('cli_pk_hex', cli_pk_hex); - await this.state.storage.put('status', 'pending'); - await this.state.storage.put('attempts_remaining', MAX_CODE_ATTEMPTS); - await this.state.storage.setAlarm(Date.now() + REQUEST_TTL_SECONDS * 1000); - - return cors(new Response(null, { status: 204 })); - } - - private async handleGetPublicKey(): Promise { - const cli_pk_hex = await this.state.storage.get('cli_pk_hex'); - if (!cli_pk_hex) return err('Not found', 404); - return json({ cli_pk_hex }); - } - - private async handlePostSession(request: Request): Promise { - let body: unknown; - try { - body = await request.json(); - } catch { - return err('Invalid JSON', 400); - } - const { wallet_pk_hex, nonce_hex, ciphertext_b64url, code_hash_hex } = body as Record< - string, - unknown - >; - - if (!isHex(wallet_pk_hex, 64)) return err('wallet_pk_hex must be 64 hex chars', 400); - if (!isHex(nonce_hex, 48)) return err('nonce_hex must be 48 hex chars', 400); - if (!isB64url(ciphertext_b64url)) return err('ciphertext_b64url must be base64url', 400); - if (!isHex(code_hash_hex, 64)) return err('code_hash_hex must be 64 hex chars', 400); - - const status = await this.state.storage.get('status'); - if (status !== 'pending') return err('Request not in pending state', 409); - - await this.state.storage.put('wallet_pk_hex', wallet_pk_hex); - await this.state.storage.put('nonce_hex', nonce_hex); - await this.state.storage.put('ciphertext_b64url', ciphertext_b64url); - await this.state.storage.put('code_hash_hex', code_hash_hex); - await this.state.storage.put('status', 'ready'); - - return cors(new Response(null, { status: 204 })); - } - - private async handleGetStatus(): Promise { - const status = await this.state.storage.get('status'); - if (!status) return err('Not found', 404); - return json({ status }); - } - - private async handleRetrieve(request: Request): Promise { - let body: unknown; - try { - body = await request.json(); - } catch { - return err('Invalid JSON', 400); - } - const { code_hash_hex } = body as Record; - if (!isHex(code_hash_hex, 64)) return err('code_hash_hex must be 64 hex chars', 400); - - const stored = await this.state.storage.get('code_hash_hex'); - const attempts = (await this.state.storage.get('attempts_remaining')) ?? 0; - - if (!stored) return err('Not found', 404); - if (attempts <= 0) { - await this.state.storage.deleteAll(); - return err('Expired', 410); - } - - if (!constantTimeEqual(code_hash_hex, stored)) { - const remaining = attempts - 1; - await this.state.storage.put('attempts_remaining', remaining); - if (remaining <= 0) { - await this.state.storage.deleteAll(); - return err('Expired', 410); - } - return json({ attempts_remaining: remaining }, 403); - } - - // Correct code — retrieve and delete everything - const [wallet_pk_hex, nonce_hex, ciphertext_b64url] = await Promise.all([ - this.state.storage.get('wallet_pk_hex'), - this.state.storage.get('nonce_hex'), - this.state.storage.get('ciphertext_b64url') - ]); - await this.state.storage.deleteAll(); - - return json({ wallet_pk_hex, nonce_hex, ciphertext_b64url, code_hash_hex: stored }); - } - - async alarm(): Promise { - await this.state.storage.deleteAll(); - } -} - -// --- Relay route handler (called from main Worker) --- - -export async function handleRelayRequest( - request: Request, - env: { SESSION_RELAY: DurableObjectNamespace } -): Promise { - if (request.method === 'OPTIONS') { - return cors( - new Response(null, { - status: 204, - headers: { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type' - } - }) - ); - } - - const url = new URL(request.url); - const parts = url.pathname.split('/').filter(Boolean); - // Expected: ['api', 'relay', , ] - - if (parts[0] !== 'api' || parts[1] !== 'relay') return err('Not found', 404); - - const action = parts[2]; - const rid = parts[3]; - - // POST /api/relay/request → create new relay request - if (request.method === 'POST' && action === 'request' && !rid) { - let body: unknown; - try { - body = await request.json(); - } catch { - return err('Invalid JSON', 400); - } - const { cli_pk_hex } = body as Record; - if (!isHex(cli_pk_hex, 64)) return err('cli_pk_hex must be 64 hex chars', 400); - - // Generate a random 8-char alphanumeric request ID - const bytes = new Uint8Array(8); - crypto.getRandomValues(bytes); - const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'; - const request_id = Array.from(bytes) - .map((b) => alphabet[b % alphabet.length]) - .join(''); - - const stub = env.SESSION_RELAY.get(env.SESSION_RELAY.idFromName(request_id)); - const initRes = await stub.fetch( - new Request('https://do/init', { - method: 'POST', - body: JSON.stringify({ cli_pk_hex }), - headers: { 'Content-Type': 'application/json' } - }) - ); - if (!initRes.ok) return err('Failed to initialize relay session', 500); - - return json({ request_id }); - } - - if (!rid) return err('Missing request ID', 400); - if (!/^[a-z0-9]{8}$/.test(rid)) return err('Invalid request ID', 400); - - const stub = env.SESSION_RELAY.get(env.SESSION_RELAY.idFromName(rid)); - - // GET /api/relay/request/:rid → get CLI public key - if (request.method === 'GET' && action === 'request') { - const res = await stub.fetch(new Request('https://do/public-key')); - if (!res.ok) return err('Not found', 404); - return cors(res); - } - - // POST /api/relay/session/:rid → browser posts encrypted payload - if (request.method === 'POST' && action === 'session') { - const body = await request.text(); - if (body.length > 16384) return err('Payload too large', 413); - const res = await stub.fetch( - new Request('https://do/session', { - method: 'POST', - body, - headers: { 'Content-Type': 'application/json' } - }) - ); - return cors(res); - } - - // GET /api/relay/status/:rid → poll for "pending" | "ready" - if (request.method === 'GET' && action === 'status') { - const res = await stub.fetch(new Request('https://do/status')); - if (!res.ok) return err('Not found', 404); - return cors(res); - } - - // POST /api/relay/retrieve/:rid → CLI submits code hash, gets ciphertext - if (request.method === 'POST' && action === 'retrieve') { - const body = await request.text(); - const res = await stub.fetch( - new Request('https://do/retrieve', { - method: 'POST', - body, - headers: { 'Content-Type': 'application/json' } - }) - ); - return cors(res); - } - - return err('Not found', 404); -} diff --git a/packages/connector-ui/src/tokenDirectory.ts b/packages/connector-ui/src/tokenDirectory.ts deleted file mode 100644 index 2dc5d26..0000000 --- a/packages/connector-ui/src/tokenDirectory.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { resolveNetwork } from './indexer'; - -const TOKEN_DIR_RAW = 'https://raw.githubusercontent.com/0xsequence/token-directory/main'; - -type Token = { - chainId: number; - address: string; - name: string; - symbol: string; - decimals: number; - logoURI?: string | null; -}; - -async function fetchJson(url: string): Promise { - const res = await fetch(url); - if (!res.ok) throw new Error(`fetch ${url} failed: ${res.status}`); - return res.json(); -} - -function cacheGet(key: string): any | null { - try { - const raw = localStorage.getItem(key); - if (!raw) return null; - return JSON.parse(raw); - } catch { - return null; - } -} - -function cacheSet(key: string, value: any): void { - try { - localStorage.setItem(key, JSON.stringify(value)); - } catch {} -} - -async function loadIndex(): Promise { - const key = 'tokenDirectory.index'; - const cached = cacheGet(key); - const ttlMs = 10 * 60 * 1000; - if (cached?.ts && Date.now() - cached.ts < ttlMs && cached?.data) return cached.data; - - const data = await fetchJson(`${TOKEN_DIR_RAW}/index/index.json`); - cacheSet(key, { ts: Date.now(), data }); - return data; -} - -function chainFolderFromIndex( - indexJson: any, - chainId: number -): { chainName: string; sha256: string } { - const idx = indexJson?.index; - if (!idx) throw new Error('token-directory: missing index'); - for (const [chainName, meta] of Object.entries(idx)) { - if (chainName === '_external') continue; - if (String(meta?.chainId) !== String(chainId)) continue; - const sha = meta?.tokenLists?.['erc20.json']; - if (!sha) - throw new Error(`token-directory: no erc20 list for chainId=${chainId} (${chainName})`); - return { chainName, sha256: sha }; - } - throw new Error(`token-directory: unknown chainId=${chainId}`); -} - -async function loadErc20List(chainId: number): Promise<{ tokens: Token[] }> { - const idx = await loadIndex(); - const { chainName, sha256 } = chainFolderFromIndex(idx, chainId); - - const key = `tokenDirectory.erc20.${chainId}.${String(sha256).slice(0, 12)}`; - const cached = cacheGet(key); - if (cached?.tokens) return cached; - - const data = await fetchJson(`${TOKEN_DIR_RAW}/index/${chainName}/erc20.json`); - cacheSet(key, data); - return data; -} - -export async function resolveErc20Symbol(chainId: number, symbol: string): Promise { - const sym = String(symbol || '') - .toUpperCase() - .trim(); - if (!sym) return null; - - const list = await loadErc20List(chainId); - const tokens = Array.isArray((list as any)?.tokens) ? (list as any).tokens : (list as any); - if (!Array.isArray(tokens)) throw new Error('token-directory: unexpected erc20 list format'); - - const matches = tokens.filter((t: any) => String(t?.symbol || '').toUpperCase() === sym); - if (!matches.length) return null; - - const pick = - matches.find((t: any) => t?.extensions?.verified === true) || - matches.find((t: any) => t?.logoURI) || - matches[0]; - return { - chainId: Number(pick.chainId ?? chainId), - address: pick.address, - symbol: pick.symbol, - name: pick.name, - decimals: pick.decimals, - logoURI: pick.logoURI || null - }; -} - -export function nativeSymbolForChainId(chainId: number): string { - const net = resolveNetwork(chainId); - return net?.nativeCurrency?.symbol || 'NATIVE'; -} diff --git a/packages/connector-ui/src/types.d.ts b/packages/connector-ui/src/types.d.ts deleted file mode 100644 index e69de29..0000000 diff --git a/packages/connector-ui/tsconfig.app.tsbuildinfo b/packages/connector-ui/tsconfig.app.tsbuildinfo deleted file mode 100644 index 4ead82c..0000000 --- a/packages/connector-ui/tsconfig.app.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"root":["./src/app.tsx","./src/config.ts","./src/indexer.ts","./src/main.tsx","./src/relay.ts","./src/tokendirectory.ts","./src/types.d.ts","./src/vite-env.d.ts","./src/components/codedisplay.tsx","./src/components/fundingscreen.tsx"],"version":"5.9.3"} \ No newline at end of file diff --git a/packages/connector-ui/tsconfig.node.tsbuildinfo b/packages/connector-ui/tsconfig.node.tsbuildinfo deleted file mode 100644 index cbccb2c..0000000 --- a/packages/connector-ui/tsconfig.node.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"root":["./vite.config.ts","./vite-plugins/mirror-skills.ts"],"version":"5.9.3"} \ No newline at end of file diff --git a/packages/connector-ui/vite-plugins/mirror-skills.ts b/packages/connector-ui/vite-plugins/mirror-skills.ts deleted file mode 100644 index 7bf20e4..0000000 --- a/packages/connector-ui/vite-plugins/mirror-skills.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { Plugin } from 'vite'; - -import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'; -import { dirname, resolve } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -// Mirror skills/ at the repo root onto an explicit, enumerated URL surface. -// The SKILL protocol defines one file per skill directory (SKILL.md), and -// the published surface is exactly that — nothing else from skills/ is -// served, so stray files (.DS_Store, repo-local READMEs, lint configs) -// cannot leak to the CDN. -// -// Emitted paths, derived from skills/ contents at build and dev-server -// startup: -// -// /SKILL.md <- skills/SKILL.md -// /skills/SKILL.md <- skills/SKILL.md -// /skills//SKILL.md <- skills//SKILL.md -// //SKILL.md <- skills//SKILL.md -// (flattened mirror; compat with URLs -// referenced in older CLIs' bundled -// root SKILL.md) -// -// Adding skills//SKILL.md starts serving both -// /skills//SKILL.md and //SKILL.md automatically -// on the next build. -export function mirrorSkills(): Plugin { - const here = dirname(fileURLToPath(import.meta.url)); - const skillsDir = resolve(here, '../../../skills'); - - const withinSkillsDir = (candidate: string) => - candidate === skillsDir || candidate.startsWith(`${skillsDir}/`); - - function resolveRequest(url: string): string | null { - if (url === '/SKILL.md' || url === '/skills/SKILL.md') { - return resolve(skillsDir, 'SKILL.md'); - } - const match = url.match(/^\/(?:skills\/)?([^/]+)\/SKILL\.md$/); - if (!match) return null; - return resolve(skillsDir, match[1], 'SKILL.md'); - } - - return { - name: 'mirror-skills', - configureServer(server) { - server.middlewares.use((req, res, next) => { - const url = req.url?.split('?')[0] ?? ''; - const file = resolveRequest(url); - if (file && withinSkillsDir(file) && existsSync(file) && statSync(file).isFile()) { - res.setHeader('content-type', 'text/markdown; charset=utf-8'); - res.end(readFileSync(file)); - return; - } - next(); - }); - }, - generateBundle() { - if (!existsSync(skillsDir)) return; - - const rootSkill = resolve(skillsDir, 'SKILL.md'); - if (!existsSync(rootSkill)) return; - - const emit = (fileName: string, source: Buffer) => { - this.emitFile({ type: 'asset', fileName, source }); - }; - - // Root entrypoint — served at both /SKILL.md and /skills/SKILL.md - const rootSource = readFileSync(rootSkill); - emit('SKILL.md', rootSource); - emit('skills/SKILL.md', rootSource); - - // Each sub-skill, served at both /skills//SKILL.md (structured) - // and //SKILL.md (flattened, for older-CLI URL compat) - for (const entry of readdirSync(skillsDir, { withFileTypes: true })) { - if (!entry.isDirectory()) continue; - const file = resolve(skillsDir, entry.name, 'SKILL.md'); - if (!existsSync(file)) continue; - const source = readFileSync(file); - emit(`skills/${entry.name}/SKILL.md`, source); - emit(`${entry.name}/SKILL.md`, source); - } - } - }; -} diff --git a/packages/oidc-relay/package.json b/packages/oidc-relay/package.json new file mode 100644 index 0000000..880ddbe --- /dev/null +++ b/packages/oidc-relay/package.json @@ -0,0 +1,20 @@ +{ + "name": "@polygonlabs/oidc-relay", + "version": "0.0.0", + "private": true, + "type": "module", + "description": "Public OIDC handoff relay (Cloudflare Worker) so the CLI can complete browser login from any machine, local or remote.", + "scripts": { + "deploy": "npx -y wrangler@3 deploy", + "deploy:staging": "npx -y wrangler@3 deploy --env staging", + "deploy:production": "npx -y wrangler@3 deploy --env production", + "dev": "npx -y wrangler@3 dev", + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20240712.0", + "typescript": "^5.9.3", + "vitest": "^3.0.0" + } +} diff --git a/packages/oidc-relay/src/login-session.test.ts b/packages/oidc-relay/src/login-session.test.ts new file mode 100644 index 0000000..5a8b012 --- /dev/null +++ b/packages/oidc-relay/src/login-session.test.ts @@ -0,0 +1,155 @@ +import { describe, expect, it } from 'vitest'; + +import type { SessionStore } from './login-session.ts'; + +import { LoginSessionCore, parseLoginStatus } from './login-session.ts'; + +function memoryStore(): SessionStore { + const map = new Map(); + return { + get: async (key: string) => map.get(key) as T | undefined, + put: async (entries) => { + for (const [k, v] of Object.entries(entries)) map.set(k, v); + }, + delete: async (key) => map.delete(key), + deleteAll: async () => map.clear() + }; +} + +describe('LoginSessionCore', () => { + it('reports expired before register', async () => { + const core = new LoginSessionCore(memoryStore()); + expect(await core.getStatus()).toEqual({ status: 'expired' }); + expect(await core.nextAction()).toEqual({ state: 'expired' }); + expect(await core.submitAction({ type: 'google' })).toEqual({ ok: false, error: 'expired' }); + }); + + it('register arms the session with awaiting-method', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + expect(await core.getStatus()).toEqual({ status: 'awaiting-method' }); + expect(await core.nextAction()).toEqual({ state: 'pending' }); + }); + + it('actions are one-time reads', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + await core.submitAction({ type: 'email', email: 'a@b.co' }); + expect(await core.nextAction()).toEqual({ + state: 'action', + action: { type: 'email', email: 'a@b.co' } + }); + expect(await core.nextAction()).toEqual({ state: 'pending' }); + }); + + it('a newer action replaces an unconsumed one (latest wins)', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + await core.submitAction({ type: 'google' }); + await core.submitAction({ type: 'cancel' }); + expect(await core.nextAction()).toEqual({ state: 'action', action: { type: 'cancel' } }); + }); + + it('status round-trips and is repeat-readable', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + await core.setStatus({ status: 'otp-sent' }); + expect(await core.getStatus()).toEqual({ status: 'otp-sent' }); + expect(await core.getStatus()).toEqual({ status: 'otp-sent' }); + }); + + it('rejects actions after a terminal status', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + await core.setStatus({ status: 'done', walletAddress: '0xabc' }); + expect(await core.submitAction({ type: 'otp', code: '123456' })).toEqual({ + ok: false, + error: 'finished' + }); + expect(await core.getStatus()).toEqual({ status: 'done', walletAddress: '0xabc' }); + }); + + it('deleteAll expires everything (alarm behavior)', async () => { + const store = memoryStore(); + const core = new LoginSessionCore(store); + await core.register(); + await store.deleteAll(); + expect(await core.getStatus()).toEqual({ status: 'expired' }); + }); + + it('setStatus before register does not write and leaves getStatus expired', async () => { + const core = new LoginSessionCore(memoryStore()); + expect(await core.setStatus({ status: 'otp-sent' })).toEqual({ ok: false }); + expect(await core.getStatus()).toEqual({ status: 'expired' }); + }); + + it('setStatus after register writes and reports ok', async () => { + const core = new LoginSessionCore(memoryStore()); + await core.register(); + expect(await core.setStatus({ status: 'otp-sent' })).toEqual({ ok: true }); + expect(await core.getStatus()).toEqual({ status: 'otp-sent' }); + }); +}); + +describe('parseLoginStatus', () => { + it('parses and normalizes every valid status shape', () => { + expect(parseLoginStatus({ status: 'awaiting-method' })).toEqual({ + status: 'awaiting-method' + }); + expect(parseLoginStatus({ status: 'auth-url', url: 'https://accounts.google.com' })).toEqual({ + status: 'auth-url', + url: 'https://accounts.google.com' + }); + expect(parseLoginStatus({ status: 'otp-sent' })).toEqual({ status: 'otp-sent' }); + expect(parseLoginStatus({ status: 'otp-invalid' })).toEqual({ + status: 'otp-invalid' + }); + expect(parseLoginStatus({ status: 'otp-invalid', attemptsLeft: 2 })).toEqual({ + status: 'otp-invalid', + attemptsLeft: 2 + }); + expect(parseLoginStatus({ status: 'done', walletAddress: '0xabc' })).toEqual({ + status: 'done', + walletAddress: '0xabc' + }); + expect(parseLoginStatus({ status: 'error', message: 'boom' })).toEqual({ + status: 'error', + message: 'boom' + }); + }); + + it('rejects auth-url missing its url', () => { + expect(parseLoginStatus({ status: 'auth-url' })).toEqual(null); + }); + + it('rejects a non-string message', () => { + expect(parseLoginStatus({ status: 'error', message: 123 })).toEqual(null); + }); + + it('rejects an unknown status string', () => { + expect(parseLoginStatus({ status: 'bogus' })).toEqual(null); + }); + + it('rejects non-object input', () => { + expect(parseLoginStatus(null)).toEqual(null); + expect(parseLoginStatus('done')).toEqual(null); + expect(parseLoginStatus(42)).toEqual(null); + expect(parseLoginStatus(undefined)).toEqual(null); + }); + + it('strips extra properties not part of the status shape', () => { + expect(parseLoginStatus({ status: 'otp-sent', junk: 'x' })).toEqual({ + status: 'otp-sent' + }); + expect(parseLoginStatus({ status: 'auth-url', url: 'https://example.com', junk: 'x' })).toEqual( + { + status: 'auth-url', + url: 'https://example.com' + } + ); + expect(parseLoginStatus({ status: 'done', walletAddress: '0xabc', junk: 'x' })).toEqual({ + status: 'done', + walletAddress: '0xabc' + }); + }); +}); diff --git a/packages/oidc-relay/src/login-session.ts b/packages/oidc-relay/src/login-session.ts new file mode 100644 index 0000000..07e7745 --- /dev/null +++ b/packages/oidc-relay/src/login-session.ts @@ -0,0 +1,183 @@ +// Pairing-session logic for the browser login flow. Pure logic over a minimal +// storage interface so it is unit-testable without the Workers runtime; the +// Durable Object wrapper lives in relay.ts wiring (Task 2). +// +// One pending action slot, latest wins: the page waits for a status change +// before offering the next input, so at most one action is meaningfully in +// flight; a second submit (double click, cancel during OTP) should replace, +// not queue. Actions are one-time reads so an OTP can never be replayed. + +export type LoginAction = + | { type: 'google' } + | { type: 'email'; email: string } + | { type: 'otp'; code: string } + | { type: 'cancel' } + | { type: 'oidc-callback'; callbackUrl: string }; + +export type LoginStatus = + | { status: 'awaiting-method' } + | { status: 'auth-url'; url: string } + | { status: 'otp-sent' } + | { status: 'otp-invalid'; attemptsLeft?: number } + | { status: 'done'; walletAddress: string } + | { status: 'error'; message: string }; + +const VALID_STATUS_VALUES = new Set([ + 'awaiting-method', + 'auth-url', + 'otp-sent', + 'otp-invalid', + 'done', + 'error' +]); + +// Validate and normalize a browser/CLI-submitted status before it reaches the DO. +// Performs per-field validation (status enum, string length bounds, required fields +// per status kind) and returns a reconstructed object containing only the known fields +// for that status type, preventing junk properties from reaching durable storage. +// Returns null if the input is invalid. +export function parseLoginStatus(s: unknown): LoginStatus | null { + if (typeof s !== 'object' || s === null) return null; + const status = (s as { status?: unknown }).status; + if (typeof status !== 'string' || !VALID_STATUS_VALUES.has(status)) return null; + + // Extract and validate optional fields + const url = (s as { url?: unknown }).url; + if (url !== undefined && (typeof url !== 'string' || url.length > 2048)) return null; + + const walletAddress = (s as { walletAddress?: unknown }).walletAddress; + if ( + walletAddress !== undefined && + (typeof walletAddress !== 'string' || walletAddress.length > 128) + ) + return null; + + const message = (s as { message?: unknown }).message; + if (message !== undefined && (typeof message !== 'string' || message.length > 512)) return null; + + const attemptsLeft = (s as { attemptsLeft?: unknown }).attemptsLeft; + if (attemptsLeft !== undefined && typeof attemptsLeft !== 'number') return null; + + // Reconstruct with only valid fields for this status + switch (status) { + case 'awaiting-method': + return { status: 'awaiting-method' }; + case 'auth-url': + if (typeof url !== 'string') return null; + return { status: 'auth-url', url }; + case 'otp-sent': + return { status: 'otp-sent' }; + case 'otp-invalid': + return typeof attemptsLeft === 'number' + ? { status: 'otp-invalid', attemptsLeft } + : { status: 'otp-invalid' }; + case 'done': + if (typeof walletAddress !== 'string') return null; + return { status: 'done', walletAddress }; + case 'error': + if (typeof message !== 'string') return null; + return { status: 'error', message }; + default: + return null; + } +} + +export interface SessionStore { + get(key: string): Promise; + put(entries: Record): Promise; + delete(key: string): Promise; + deleteAll(): Promise; +} + +export class LoginSessionCore { + constructor(private readonly store: SessionStore) {} + + async register(): Promise { + await this.store.put({ armed: true, status: { status: 'awaiting-method' } }); + } + + async submitAction( + action: LoginAction + ): Promise<{ ok: boolean; error?: 'expired' | 'finished' }> { + if (!(await this.store.get('armed'))) return { ok: false, error: 'expired' }; + const status = await this.store.get('status'); + if (status && (status.status === 'done' || status.status === 'error')) { + return { ok: false, error: 'finished' }; + } + await this.store.put({ pendingAction: action }); + return { ok: true }; + } + + async nextAction(): Promise< + { state: 'expired' } | { state: 'pending' } | { state: 'action'; action: LoginAction } + > { + if (!(await this.store.get('armed'))) return { state: 'expired' }; + const action = await this.store.get('pendingAction'); + if (!action) return { state: 'pending' }; + await this.store.delete('pendingAction'); + return { state: 'action', action }; + } + + async setStatus(status: LoginStatus): Promise<{ ok: boolean }> { + if (!(await this.store.get('armed'))) return { ok: false }; + await this.store.put({ status }); + return { ok: true }; + } + + async getStatus(): Promise { + if (!(await this.store.get('armed'))) return { status: 'expired' }; + return (await this.store.get('status')) ?? { status: 'expired' }; + } +} + +const SESSION_TTL_MS = 10 * 60 * 1000; // 10 minutes to complete the login + +function doStore(storage: DurableObjectStorage): SessionStore { + return { + get: (key) => storage.get(key), + put: (entries) => storage.put(entries), + delete: (key) => storage.delete(key), + deleteAll: () => storage.deleteAll() + }; +} + +// --- Durable Object: one instance per login session id --- +export class LoginSession { + private readonly core: LoginSessionCore; + constructor(private readonly state: DurableObjectState) { + this.core = new LoginSessionCore(doStore(state.storage)); + } + + async fetch(request: Request): Promise { + const url = new URL(request.url); + const op = url.pathname; // internal path set by the router in relay.ts + + if (op === '/register') { + await this.core.register(); + await this.state.storage.setAlarm(Date.now() + SESSION_TTL_MS); + return new Response(null, { status: 204 }); + } + if (op === '/action') { + const action = (await request.json()) as LoginAction; + const result = await this.core.submitAction(action); + if (!result.ok) return Response.json({ error: result.error }, { status: 410 }); + return new Response(null, { status: 204 }); + } + if (op === '/next-action') { + return Response.json(await this.core.nextAction()); + } + if (op === '/set-status') { + const result = await this.core.setStatus(await request.json()); + if (!result.ok) return Response.json({ error: 'expired' }, { status: 410 }); + return new Response(null, { status: 204 }); + } + if (op === '/get-status') { + return Response.json(await this.core.getStatus()); + } + return new Response('not found', { status: 404 }); + } + + async alarm(): Promise { + await this.state.storage.deleteAll(); + } +} diff --git a/packages/oidc-relay/src/relay.test.ts b/packages/oidc-relay/src/relay.test.ts new file mode 100644 index 0000000..051555f --- /dev/null +++ b/packages/oidc-relay/src/relay.test.ts @@ -0,0 +1,58 @@ +import { describe, expect, it } from 'vitest'; + +import { validAction, validCallbackUrl } from './relay.ts'; + +describe('validCallbackUrl', () => { + it('accepts the production and staging agentconnect login pages over https', () => { + expect(validCallbackUrl('https://agentconnect.polygon.technology/login#abc')).toBe(true); + expect(validCallbackUrl('https://agentconnect.staging.polygon.technology/login#abc')).toBe( + true + ); + }); + + it('accepts localhost over http for local dev', () => { + expect(validCallbackUrl('http://localhost:5173/login#abc')).toBe(true); + }); + + it('rejects a lookalike host that merely starts with localhost', () => { + expect(validCallbackUrl('http://localhost.evil.example/x')).toBe(false); + }); + + it('rejects a numeric prefix collision with 127.0.0.1', () => { + expect(validCallbackUrl('http://127.0.0.100/x')).toBe(false); + }); + + it('rejects a non-URL string', () => { + expect(validCallbackUrl('not a url')).toBe(false); + }); + + it('rejects an https URL on a non-allowlisted host', () => { + expect(validCallbackUrl('https://evil.example/login')).toBe(false); + }); + + it('rejects a URL longer than 2048 characters', () => { + expect(validCallbackUrl(`https://agentconnect.polygon.technology/${'a'.repeat(2050)}`)).toBe( + false + ); + }); +}); + +describe('validAction', () => { + it('accepts an oidc-callback action with a good callback URL', () => { + expect( + validAction({ + type: 'oidc-callback', + callbackUrl: 'https://agentconnect.polygon.technology/login#abc' + }) + ).toBe(true); + }); + + it('rejects an oidc-callback action with a bad callback URL', () => { + expect( + validAction({ + type: 'oidc-callback', + callbackUrl: 'https://evil.example/login' + }) + ).toBe(false); + }); +}); diff --git a/packages/oidc-relay/src/relay.ts b/packages/oidc-relay/src/relay.ts new file mode 100644 index 0000000..1808a24 --- /dev/null +++ b/packages/oidc-relay/src/relay.ts @@ -0,0 +1,182 @@ +// Browser-login pairing relay (Cloudflare Worker + Durable Object). +// +// Purpose: let a CLI on ANY machine (including a remote server / openclaw) drive +// a browser-based login. The CLI arms a pairing session, the browser page polls +// for status and submits the chosen login method (Google, email, OTP), and the +// CLI polls for that input. The OMS relay now owns the Google OAuth callback +// itself; this relay only carries pairing state between the CLI and the page, +// including the `oidc-callback` action the page submits once the OMS relay +// returns the browser to it. +// +// Endpoints (all under /api/login): +// POST /register { session } (CLI: arm a pairing session) +// POST /action { session, action } (browser: submit user input) +// GET /next-action?session= -> { state, action? } (CLI: poll for input, one-time read) +// POST /status { session, ...LoginStatus } (CLI: publish state) +// GET /status?session= -> LoginStatus (browser: poll state, repeat-readable) + +import type { LoginAction } from './login-session.ts'; + +import { LoginSession, parseLoginStatus } from './login-session.ts'; + +export { LoginSession }; + +interface Env { + LOGIN_SESSION: DurableObjectNamespace; +} + +function cors(res: Response): Response { + const h = new Headers(res.headers); + h.set('Access-Control-Allow-Origin', '*'); + h.set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS'); + h.set('Access-Control-Allow-Headers', 'Content-Type'); + return new Response(res.body, { status: res.status, headers: h }); +} +function json(data: unknown, status = 200): Response { + return cors(Response.json(data, { status })); +} + +function validSession(s: string | null): s is string { + return typeof s === 'string' && /^[A-Za-z0-9_-]{16,64}$/.test(s); +} + +// Host allowlist for the oidc-callback URL. The callbackUrl is always our own +// agentconnect /login page (the omsRelayReturnUri) that the OMS relay returned +// the browser to, so only those hosts (plus localhost for dev) are accepted. +const ALLOWED_RETURN_HOSTS = new Set([ + 'agentconnect.polygon.technology', + 'agentconnect.staging.polygon.technology', + 'localhost', + '127.0.0.1' +]); + +// Bound the callback URL the browser hands back after the OMS relay finishes the +// Google OAuth leg. It must be an https URL, or an http localhost/127.0.0.1 URL +// for local dev, on one of the allowlisted hosts, so a junk or spoofed value +// can't be smuggled through as an action. +export function validCallbackUrl(u: unknown): u is string { + if (typeof u !== 'string' || u.length === 0 || u.length > 2048) return false; + let url: URL; + try { + url = new URL(u); + } catch { + return false; + } + const isLocal = url.hostname === 'localhost' || url.hostname === '127.0.0.1'; + if (url.protocol !== 'https:' && !(isLocal && url.protocol === 'http:')) return false; + return ALLOWED_RETURN_HOSTS.has(url.hostname); +} + +// Shape-check browser-submitted actions before they reach the DO. +export function validAction(a: unknown): a is LoginAction { + if (typeof a !== 'object' || a === null) return false; + const t = (a as { type?: unknown }).type; + if (t === 'google' || t === 'cancel') return true; + if (t === 'email') { + const email = (a as { email?: unknown }).email; + return ( + typeof email === 'string' && email.length >= 3 && email.length <= 320 && email.includes('@') + ); + } + if (t === 'otp') { + const code = (a as { code?: unknown }).code; + return typeof code === 'string' && code.length >= 4 && code.length <= 16; + } + if (t === 'oidc-callback') { + return validCallbackUrl((a as { callbackUrl?: unknown }).callbackUrl); + } + return false; +} + +// --- Worker entry / router --- +// Cloudflare Workers require a default export (the module's fetch handler), so +// the repo-wide "prefer named exports" rule doesn't apply to this entry point. +// eslint-disable-next-line import-x/no-default-export +export default { + async fetch(request: Request, env: Env): Promise { + const url = new URL(request.url); + if (request.method === 'OPTIONS') return cors(new Response(null, { status: 204 })); + + // GET / or /health -> liveness check (confirm the worker is deployed/reachable). + if (request.method === 'GET' && (url.pathname === '/' || url.pathname === '/health')) { + return json({ ok: true, service: 'oidc-relay' }); + } + + // --- Browser-login pairing sessions (/api/login/*) --- + const loginStub = (session: string) => + env.LOGIN_SESSION.get(env.LOGIN_SESSION.idFromName(session)); + + // POST /api/login/register { session } -> arm a pairing session (CLI). + if (request.method === 'POST' && url.pathname === '/api/login/register') { + let body: { session?: unknown }; + try { + body = (await request.json()) as { session?: unknown }; + } catch { + return json({ error: 'invalid json' }, 400); + } + const session = typeof body.session === 'string' ? body.session : null; + if (!validSession(session)) return json({ error: 'invalid session' }, 400); + await loginStub(session).fetch(new Request('https://do/register', { method: 'POST' })); + return cors(new Response(null, { status: 204 })); + } + + // POST /api/login/action { session, action } -> browser submits user input. + if (request.method === 'POST' && url.pathname === '/api/login/action') { + let body: { session?: unknown; action?: unknown }; + try { + body = (await request.json()) as { session?: unknown; action?: unknown }; + } catch { + return json({ error: 'invalid json' }, 400); + } + const session = typeof body.session === 'string' ? body.session : null; + if (!validSession(session) || !validAction(body.action)) { + return json({ error: 'invalid request' }, 400); + } + const res = await loginStub(session).fetch( + new Request('https://do/action', { + method: 'POST', + body: JSON.stringify(body.action) + }) + ); + return cors(res); + } + + // GET /api/login/next-action?session= -> CLI polls for user input (one-time read). + if (request.method === 'GET' && url.pathname === '/api/login/next-action') { + const session = url.searchParams.get('session'); + if (!validSession(session)) return json({ error: 'invalid session' }, 400); + return cors(await loginStub(session).fetch(new Request('https://do/next-action'))); + } + + // POST /api/login/status { session, ...LoginStatus } -> CLI publishes state. + if (request.method === 'POST' && url.pathname === '/api/login/status') { + let body: { session?: unknown; status?: unknown }; + try { + body = (await request.json()) as { session?: unknown; status?: unknown }; + } catch { + return json({ error: 'invalid json' }, 400); + } + const session = typeof body.session === 'string' ? body.session : null; + const parsed = parseLoginStatus(body.status); + if (!validSession(session) || parsed === null) { + return json({ error: 'invalid request' }, 400); + } + const res = await loginStub(session).fetch( + new Request('https://do/set-status', { + method: 'POST', + body: JSON.stringify(parsed) + }) + ); + return cors(res); + } + + // GET /api/login/status?session= -> browser polls state (repeat-readable). + if (request.method === 'GET' && url.pathname === '/api/login/status') { + const session = url.searchParams.get('session'); + if (!validSession(session)) return json({ status: 'error', message: 'invalid session' }, 400); + return cors(await loginStub(session).fetch(new Request('https://do/get-status'))); + } + + return new Response('not found', { status: 404 }); + } +}; diff --git a/packages/oidc-relay/tsconfig.json b/packages/oidc-relay/tsconfig.json new file mode 100644 index 0000000..8742235 --- /dev/null +++ b/packages/oidc-relay/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "es2022", + "module": "es2022", + "moduleResolution": "bundler", + "lib": ["es2023"], + "types": ["@cloudflare/workers-types"], + "strict": true, + "skipLibCheck": true, + "noEmit": true, + "esModuleInterop": true, + "allowImportingTsExtensions": true + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/oidc-relay/wrangler.toml b/packages/oidc-relay/wrangler.toml new file mode 100644 index 0000000..f2dccc0 --- /dev/null +++ b/packages/oidc-relay/wrangler.toml @@ -0,0 +1,67 @@ +name = "oidc-relay" +compatibility_date = "2024-09-23" +workers_dev = true +send_metrics = false + +main = "src/relay.ts" + +[[durable_objects.bindings]] +name = "LOGIN_SESSION" +class_name = "LoginSession" + +[[migrations]] +tag = "v1" +new_classes = ["OidcHandoff"] + +[[migrations]] +tag = "v2" +new_classes = ["LoginSession"] + +[[migrations]] +tag = "v3" +deleted_classes = ["OidcHandoff"] + +# Staging: a workers.dev URL is fine to start; swap to a custom domain for prod. +[env.staging] +name = "oidc-relay-staging" +workers_dev = true + +[[env.staging.durable_objects.bindings]] +name = "LOGIN_SESSION" +class_name = "LoginSession" + +[[env.staging.migrations]] +tag = "v1" +new_classes = ["OidcHandoff"] + +[[env.staging.migrations]] +tag = "v2" +new_classes = ["LoginSession"] + +[[env.staging.migrations]] +tag = "v3" +deleted_classes = ["OidcHandoff"] + +[env.production] +name = "oidc-relay-production" +workers_dev = false +# Custom domain provisioned by wrangler on deploy (polygon.technology zone must be +# on this Cloudflare account). The Sequence/OMS allowlist target is now the +# agentconnect `omsRelayReturnUri`, not this worker (see design doc). +routes = [{ pattern = "oidc-relay.polygon.technology", custom_domain = true }] + +[[env.production.durable_objects.bindings]] +name = "LOGIN_SESSION" +class_name = "LoginSession" + +[[env.production.migrations]] +tag = "v1" +new_classes = ["OidcHandoff"] + +[[env.production.migrations]] +tag = "v2" +new_classes = ["LoginSession"] + +[[env.production.migrations]] +tag = "v3" +deleted_classes = ["OidcHandoff"] diff --git a/packages/polygon-agent-cli/README.md b/packages/polygon-agent-cli/README.md index 283a297..81cd4af 100644 --- a/packages/polygon-agent-cli/README.md +++ b/packages/polygon-agent-cli/README.md @@ -16,7 +16,7 @@ - [Overview](#overview) - [Quickstart](#quickstart) - [Core Components](#core-components) - - [Sequence: Wallet Infrastructure](#sequence-wallet-infrastructure) + - [OMS: Wallet Infrastructure](#oms-wallet-infrastructure) - [Trails: Swapping, Bridging, and onchain actions](#trails-swapping-bridging-and-defi-actions) - [Onchain Identity](#onchain-agentic-identity) - [Plugins & Skills](#plugins--skills) @@ -32,7 +32,7 @@ Polygon Agent CLI gives AI agents everything they need to operate onchain: -- **Create and manage wallets** define allowances, session limits, and contract permissions in order to transact securely. Mitigates risk of prompt injection attacks. Private keys never leave the device and have to be exposed to your agent's context. +- **Create and manage wallets** browser-login embedded smart wallets, no private keys to manage and no keys exposed to your agent's context. - **Send tokens, swap, bridge or any action** pay in any token for any onchain action. Built-in swapping, bridging, deposits, DeFi primitives, and more. - **Register agent identity** and build reputation via ERC-8004 - **Integrated APIs** query cross-chain balances, transaction history and or query nodes via dedicated RPCs @@ -50,7 +50,7 @@ Install the Polygon Agent CLI as a skill your agent can use — works with Claud npx skills add https://github.com/0xPolygon/polygon-agent-cli ``` -Once installed, your agent has access to wallet management, token operations, DEX swaps, and on-chain identity, all through the `polygon-agent` CLI. +Once installed, your agent has access to wallet management, token operations, DEX swaps, and on-chain identity, all through the `agent` CLI. The long-form `polygon-agent` command name remains available as an alias, so both work. ### Manual Install @@ -60,7 +60,7 @@ Once installed, your agent has access to wallet management, token operations, DE npm install -g @polygonlabs/agent-cli ``` -**From source** — for contributors or local development. Use `pnpm polygon-agent` instead of `polygon-agent` for all commands. +**From source** — for contributors or local development. Use `pnpm polygon-agent` instead of `agent` for all commands. ```bash git clone https://github.com/0xPolygon/polygon-agent-cli.git @@ -71,32 +71,34 @@ pnpm polygon-agent --help ### After install: get your agent running -Once installed via skills or npm, run the following. If running from source, prefix `polygon-agent` commands with `pnpm` and run them from the root of the repository (e.g., `pnpm polygon-agent setup --name "MyAgent"`). +Once installed via skills or npm, run the following. If running from source, run `agent` commands via `pnpm polygon-agent` from the root of the repository (e.g., `pnpm polygon-agent setup --name "MyAgent"`). ```bash -# 1. Setup: creates EOA, authenticates, gets project access key -polygon-agent setup --name "MyAgent" - -# 2. Set your access key -export SEQUENCE_PROJECT_ACCESS_KEY= - -# 3. Create a wallet (opens browser, auto-waits for approval) -polygon-agent wallet create - -# 4. Fund the wallet -polygon-agent fund - -# 5. Start operating (SEQUENCE_INDEXER_ACCESS_KEY is the same as your project access key) -export SEQUENCE_INDEXER_ACCESS_KEY=$SEQUENCE_PROJECT_ACCESS_KEY -polygon-agent balances -polygon-agent send --to 0x... --amount 1.0 -polygon-agent swap --from USDC --to USDT --amount 5 - -# 6. Register your agent on-chain -polygon-agent agent register --name "MyAgent" +# 1. Log in to your embedded wallet in the browser +agent wallet login +# Prints a login page URL and opens it in a browser. Choose Google or email +# on the page; once you finish, the embedded wallet is created or unlocked. +# This works whether the browser is on this machine or elsewhere, so there +# is no separate remote mode to enable. Use --local for the older loopback +# flow, which needs the browser on this same machine. +# +# No setup step needed: the CLI ships a default OMS Builder publishable key, +# and login automatically provisions your own Builder project + access key +# (saved to ~/.polygon-agent/builder.json) for indexer and Trails quota. + +# 2. Fund the wallet +agent fund + +# 3. Start operating +agent balances +agent send --to 0x... --amount 1.0 +agent swap --from USDC --to USDT --amount 5 + +# 4. Register your agent on-chain +agent agent register --name "MyAgent" ``` -> Omit `--broadcast` on any command to preview without sending. See [`QUICKSTART.md`](skills/QUICKSTART.md) for the full step-by-step walkthrough. +> Omit `--broadcast` on any command to preview without sending. See [`SKILL.md`](skills/SKILL.md) for the full agent-consumable reference. --- @@ -104,17 +106,17 @@ polygon-agent agent register --name "MyAgent" The CLI is built on three pillars to enable end to end onchain payments with your agents. -### Sequence: Wallet Infrastructure +### OMS: Wallet Infrastructure -[Sequence](https://sequence.xyz) powers all wallet operations, RPC access, and indexing. +[OMS (Open Money Stack)](https://sequence.xyz) powers all wallet operations, RPC access, and indexing. | Capability | What it does | CLI command | | ----------- | ------------------------------------------------------------------------------------------- | ------------------------------- | -| **Wallets** | Session-based smart contract wallets (Account Abstraction) with scoped spending permissions | `wallet create`, `wallet list` | +| **Wallets** | browser-login embedded smart wallets (Account Abstraction), chain-agnostic address | `wallet login`, `wallet list` | | **RPCs** | Load balanced RPCs cross-chain for onchain interactions and node queries | Used internally by all commands | | **Indexer** | Token balance queries and transaction history across ERC-20/721/1155 | `balances` | -Wallet sessions are created through a secure handshake between the CLI, the Connector UI, and the Sequence Ecosystem Wallet. Session permissions let you cap spending per token, whitelist contracts, and set time-based expiry and to mitigate against prompt injection attacks. +Wallets are created and unlocked via browser login (Google or email). The embedded wallet can call any contract and spend any amount it holds; there is no contract whitelist or per-token spend limit. The wallet address is the same across every supported chain, and sessions last about a week before you re-run `wallet login`. ### Trails: Swapping, Bridging, and DeFi Actions @@ -134,7 +136,7 @@ Native contracts for agent identity, reputation, and emerging payment standards. | --------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------ | | **ERC-8004** | Register agents as ERC-721 NFTs with metadata and on-chain reputation | `agent register`, `agent reputation`, `agent feedback` | | **x402** | HTTP-native micropayment protocol for agentic payments to your favorite services | `x402-pay` | -| **Native Apps** | Direct interaction with smart contracts | Via `--contract` whitelisting | +| **Native Apps** | Direct interaction with any smart contract | `call` | **ERC-8004 contracts on Polygon:** @@ -153,7 +155,7 @@ The CLI ships with agent-friendly documentation designed to be consumed directly Once installed, the agent receives the full skill context — including wallet setup, token operations, and ERC-8004 registration, and can execute autonomously. -See [`SKILL.md`](skills/SKILL.md) for the full agent-consumable reference and [`QUICKSTART.md`](skills/QUICKSTART.md) for the 4-phase setup guide. +See [`SKILL.md`](skills/SKILL.md) for the full agent-consumable reference. --- @@ -162,38 +164,42 @@ See [`SKILL.md`](skills/SKILL.md) for the full agent-consumable reference and [` ### Setup & Wallets ```bash -polygon-agent setup --name # Create EOA + project -polygon-agent wallet create # Create wallet (auto-wait) -polygon-agent wallet create --no-wait # Manual approval flow -polygon-agent wallet list # Show all wallets -polygon-agent wallet address # Show wallet address -polygon-agent fund # Open funding widget +agent wallet login [--name ] [--local] [--no-fund] [--force] # Log in from the browser (choose Google or email on the login page); auto-provisions Builder credentials +agent setup --oms-publishable-key # Advanced: point at your own OMS Builder project instead of the default +agent wallet logout [--name ] # Log out of a wallet +agent wallet list # Show all wallets +agent wallet address [--name ] # Show wallet address (same on every chain) +agent wallet remove [--name ] # Remove a stored wallet +agent fund # Open funding widget ``` ### Token Operations ```bash -polygon-agent balances # Balances on session default chain -polygon-agent balances --chain arbitrum # Single chain override -polygon-agent balances --chains polygon,base,arbitrum # Same wallet, multiple chains (JSON) -polygon-agent send --to 0x... --amount 1.0 # Send POL (dry-run) -polygon-agent send --symbol USDC --to 0x... --amount 10 --broadcast -polygon-agent swap --from USDC --to USDT --amount 5 --broadcast -polygon-agent withdraw --position --amount max [--chain ] # dry-run; add --broadcast -polygon-agent withdraw --position --amount 0.5 --chain mainnet --broadcast # partial (underlying units) +agent balances # Balances on session default chain +agent balances --chain arbitrum # Single chain override +agent balances --chains polygon,base,arbitrum # Same wallet, multiple chains (JSON) +agent send --to 0x... --amount 1.0 # Send POL (dry-run) +agent send --symbol USDC --to 0x... --amount 10 --broadcast +agent swap --from USDC --to USDT --amount 5 --broadcast +agent withdraw --position --amount max [--chain ] # dry-run; add --broadcast +agent withdraw --position --amount 0.5 --chain mainnet --broadcast # partial (underlying units) +agent call --to 0x... --data 0x... [--value ] [--prefer-native-fee] [--broadcast] # arbitrary contract call ``` **`withdraw`** exits **Aave v3** positions using your **aToken** address (`POOL()` + `UNDERLYING_ASSET_ADDRESS()` → `Pool.withdraw`), or **ERC-4626** vaults (e.g. Morpho) via `redeem`. Dry-run prints `poolAddress` / `vault` and calldata. -For **`--broadcast`**, the session must allow the **pool or vault** and (on that chain) **fee / underlying ERC-20** touches — use `wallet create --chain --contract --contract `. If your default session is Polygon but you transact on **mainnet**, create or extend a **mainnet** session for that chain. +The embedded wallet can call any contract on any chain, so no pre-authorization is needed — just ensure the wallet holds a little POL or USDC for gas on the target chain. To transact on a chain other than Polygon, pass `--chain ` on the command itself. + +**`call`** sends a raw transaction to any contract. The relayer takes its gas fee in USDC or POL, whichever the wallet can afford; for a native-only wallet, pass `--prefer-native-fee`. ### Agent Registry (ERC-8004) ```bash -polygon-agent agent register --name "MyAgent" --broadcast -polygon-agent agent reputation --agent-id -polygon-agent agent feedback --agent-id --value 4.5 --broadcast -polygon-agent agent reviews --agent-id +agent agent register --name "MyAgent" --broadcast +agent agent reputation --agent-id +agent agent feedback --agent-id --value 4.5 --broadcast +agent agent reviews --agent-id ``` ### Smart Defaults @@ -203,46 +209,41 @@ polygon-agent agent reviews --agent-id | Wallet name | `main` | `--name ` | | Chain | `polygon` | `--chain ` | | Multi-chain balances | — | `--chains ` (comma-separated, max 20; overrides `--chain`) | -| Wallet create | Auto-wait for approval | `--no-wait` | | Broadcast | Dry-run (preview) | `--broadcast` | --- ## Environment Variables -**One key covers everything:** `SEQUENCE_INDEXER_ACCESS_KEY` and `TRAILS_API_KEY` are the same value as `SEQUENCE_PROJECT_ACCESS_KEY`: +No environment variables are required. The CLI ships a default OMS Builder publishable key, and `wallet login` automatically provisions your own Builder project and access key on first login, saving it to `~/.polygon-agent/builder.json`. -```bash -export SEQUENCE_PROJECT_ACCESS_KEY= -export SEQUENCE_INDEXER_ACCESS_KEY=$SEQUENCE_PROJECT_ACCESS_KEY -export TRAILS_API_KEY=$SEQUENCE_PROJECT_ACCESS_KEY -``` +**Advanced overrides:** -**Optional:** - -| Variable | Default | Description | -| ---------------------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `SEQUENCE_ECOSYSTEM_CONNECTOR_URL` | `https://agentconnect.polygon.technology/` | URL of the Connector UI that users open in a browser to approve wallet sessions. Override to point at a local dev server (`http://localhost:4444`) or a custom deployment. | -| `SEQUENCE_DAPP_ORIGIN` | `https://agentconnect.polygon.technology` | Origin passed to the wallet during session creation. Identifies which dapp is requesting access. Override only if running the connector under a different domain. | +| Variable | Default | Description | +| -------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------- | +| `OMS_PUBLISHABLE_KEY` | Baked-in default | Point at your own OMS Builder project instead of the default. Can also be set via `setup --oms-publishable-key ` (persists to `~/.polygon-agent/builder.json`). | +| `TRAILS_API_KEY` | — | Optional Trails API key for higher rate limits on swap / bridge / earn calls. | +| `POLYGON_AGENT_LOGIN_UI` | `https://agentconnect.polygon.technology` | Base URL of the browser login page opened by `wallet login`. | +| `POLYGON_AGENT_OIDC_RELAY` | `https://oidc-relay.polygon.technology` | Base URL of the OIDC handoff and login relay used by `wallet login`. | --- ## Security -- **Keys never leave the device.** Credentials are encrypted at rest in `~/.polygon-agent/`. Importantly, keys don't have to be exposed to the agent's context. -- **Session permissions are scoped.** Per-session spending limits, contract whitelists, and 24-hour expiry. +- **No keys to manage.** The embedded wallet is unlocked via browser login (Google or email); there are no private keys exposed to the agent's context. Credentials are stored in `~/.polygon-agent/`. +- **Sessions expire.** Wallet sessions last about a week, after which you re-run `wallet login`. --- ## Troubleshooting -| Issue | Fix | -| ------------------------------------- | ----------------------------------- | -| `Missing SEQUENCE_PROJECT_ACCESS_KEY` | Run `setup` first | -| Session expired | Re-run `wallet create` | -| Insufficient funds | Run `fund` to top up your wallet | -| Transaction failed | Omit `--broadcast` to dry-run first | -| Callback timeout | Increase with `--timeout 600` | +| Issue | Fix | +| ------------------------------------------- | ------------------------------------------------ | +| Builder provisioning failed during login (see the stderr note) | It retries on the next `wallet login`; or run `setup` manually. Custom projects: export `OMS_PUBLISHABLE_KEY` | +| Not logged in | Run `agent wallet login` | +| Session expired | Run `agent wallet login` | +| Insufficient funds / can't pay gas | Run `fund`; for a native-only wallet pass `--prefer-native-fee` on `call` | +| Transaction failed | Omit `--broadcast` to dry-run first | --- @@ -254,9 +255,6 @@ pnpm install # CLI (via root script) pnpm polygon-agent --help - -# Connector UI -cd packages/connector-ui && pnpm dev ``` ### Project Structure @@ -264,20 +262,19 @@ cd packages/connector-ui && pnpm dev ```text polygon-agent-cli/ ├── packages/ -│ ├── polygon-agent-cli/ # CLI package (@polygonlabs/agent-cli) -│ │ ├── src/ # TypeScript source -│ │ │ ├── index.ts # yargs entry point -│ │ │ ├── commands/ # Command modules (setup, wallet, operations, agent) -│ │ │ ├── lib/ # Shared utils (storage, ethauth, tokens, dapp-client) -│ │ │ └── types.d.ts # Ambient declarations for untyped deps -│ │ ├── contracts/ # ERC-8004 ABIs -│ │ └── skills/ # Agent-friendly docs (SKILL.md, QUICKSTART.md) -│ └── connector-ui/ # React app, wallet connect bridge +│ └── polygon-agent-cli/ # CLI package (@polygonlabs/agent-cli) +│ ├── src/ # TypeScript source +│ │ ├── index.ts # yargs entry point +│ │ ├── commands/ # Command modules (setup, wallet, operations, agent) +│ │ ├── lib/ # Shared utils (storage, ethauth, tokens) +│ │ └── types.d.ts # Ambient declarations for untyped deps +│ ├── contracts/ # ERC-8004 ABIs +│ └── skills/ # Agent-friendly docs (SKILL.md) ├── pnpm-workspace.yaml └── package.json ``` -**Requirements:** Node.js 20+ +**Requirements:** Node.js 22+ --- diff --git a/packages/polygon-agent-cli/package.json b/packages/polygon-agent-cli/package.json index 8f52ea4..65577aa 100644 --- a/packages/polygon-agent-cli/package.json +++ b/packages/polygon-agent-cli/package.json @@ -12,6 +12,7 @@ "access": "public" }, "bin": { + "agent": "dist/index.js", "polygon-agent": "dist/index.js" }, "files": [ @@ -23,25 +24,14 @@ "prepublishOnly": "pnpm run build", "dev": "tsx src/index.ts", "lint": "eslint .", + "test": "vitest run", "typecheck": "tsc --noEmit", "clean": "rm -rf dist node_modules *.tsbuildinfo" }, "dependencies": { - "@0xsequence/abi": "3.0.0-beta.17", - "@0xsequence/api": "3.0.0-beta.17", - "@0xsequence/builder": "3.0.0-beta.17", - "@0xsequence/dapp-client": "3.0.0-beta.17", - "@0xsequence/dapp-client-cli": "0.1.5", - "@0xsequence/indexer": "^2.3.40", "@0xsequence/network": "^2.3.40", - "@0xsequence/relayer": "3.0.0-beta.17", - "@0xsequence/wallet-core": "3.0.0-beta.17", - "@0xsequence/wallet-primitives": "3.0.0-beta.17", - "@0xsequence/wallet-wdk": "3.0.0-beta.17", "@0xtrails/api": "^0.10.4", - "@noble/ciphers": "^1.2.1", - "@noble/curves": "^1.8.1", - "@noble/hashes": "^1.7.2", + "@polygonlabs/oms-wallet": "0.2.0", "@polymarket/clob-client-v2": "^1.0.0", "@polymarket/sdk": "^6.0.1", "@x402/core": "^2.3.1", @@ -54,18 +44,16 @@ "ink-spinner": "^5.0.0", "open": "^10.1.0", "react": "^18.3.1", - "tweetnacl": "^1.0.3", - "tweetnacl-sealedbox-js": "^1.2.0", - "viem": "^2.45.3", + "viem": "^2.48.4", "yargs": "^17.7.2" }, "devDependencies": { - "@polygonlabs/agent-shared": "workspace:*", "@types/react": "^18.3.1", "@types/yargs": "^17.0.33", - "esbuild": "^0.28.0" + "esbuild": "^0.28.0", + "vitest": "^3.0.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=22" } } diff --git a/packages/polygon-agent-cli/skills/polygon-defi/SKILL.md b/packages/polygon-agent-cli/skills/polygon-defi/SKILL.md index cce137e..2481e8b 100644 --- a/packages/polygon-agent-cli/skills/polygon-defi/SKILL.md +++ b/packages/polygon-agent-cli/skills/polygon-defi/SKILL.md @@ -5,6 +5,18 @@ description: DeFi operations on Polygon using the Polygon Agent CLI. Covers same # Polygon DeFi Skill +## Session Prerequisites + +**Before any DeFi operation, the wallet must be logged in.** The embedded wallet can call any contract and spend any amount it holds — there is no contract whitelist and no per-token spend limit, so no special setup is needed for deposits, swaps, or withdrawals. If the user is not logged in, log in now: + +```bash +polygon-agent wallet login +``` + +This logs in with Google in the browser: the command prints/opens a Google sign-in URL, and after you sign in the embedded wallet is created/unlocked. On a headless/remote host add `--remote` (uses a public OIDC relay). The wallet address is the same across all chains. Sessions last about a week; if calls start failing with an expired-session error, just re-run `wallet login`. + +--- + ## Swap Tokens (Same-Chain) ```bash @@ -56,7 +68,7 @@ All request fields are optional — omit any you don't need to filter on. ### Fetch (agent code) -The API key is the project access key already available to the agent (`SEQUENCE_PROJECT_ACCESS_KEY`). +No API key is required for this public endpoint (an optional `TRAILS_API_KEY` can be set for higher rate limits). ```typescript const res = await fetch('https://trails-api.sequence.app/rpc/Trails/GetEarnPools', { @@ -108,7 +120,9 @@ interface PoolTokenInfo { Pool discovery uses `TrailsApi.getEarnPools` — picks the most liquid pool (highest TVL) for the asset. Only Polygon mainnet (chainId 137) is supported. No hardcoded addresses — the pool is resolved at runtime. -**Gas requirement:** The wallet needs POL for gas, or a session created with `--usdc-limit` to enable USDC paymaster. If the wallet has no POL, create the session with `--usdc-limit 5`. When USDC paymaster is active and the deposit amount would consume the full balance, the CLI auto-reserves 0.05 USDC for gas and prints a note. +**Gas requirement:** The relayer pays gas in USDC or POL, whichever the wallet can afford — so the only requirement is that the wallet holds the funds being deposited plus a little POL or USDC for gas. When the deposit amount would consume the full USDC balance, the CLI auto-reserves a small amount for gas and prints a note. + +The embedded wallet can call any contract, so deposits work without pre-authorizing the token or pool contract — just dry-run, then broadcast: ```bash # Dry-run — shows pool name, APY, TVL, and deposit address before committing @@ -146,62 +160,13 @@ polygon-agent withdraw --position --amount 0.5 --chain mainnet --broadc polygon-agent withdraw --position --amount max --chain polygon --broadcast ``` -### Session Prerequisites for DeFi - -Before running deposits, swaps, or withdrawals, create the wallet session with `--defi` so the relevant token and vault contracts are whitelisted: - -```bash -polygon-agent wallet create --defi -``` - -Without `--defi`, only USDC and USDC.e are whitelisted by default. The `--defi` flag adds USDT, WETH, and all supported yield vault addresses (Aave and Morpho on Polygon mainnet). - -**Same chain as the transaction:** if you use `withdraw --chain mainnet`, create or refresh the session with **`wallet create --chain mainnet --defi`**. Include **`--contract`** for the **underlying ERC-20** on that chain (e.g. mainnet USDC `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48`) since `--defi` only covers Polygon mainnet contracts. Tight **`--usdc-limit`** can block fee/helper transfers — omit or relax for yield exits. - -### Session Whitelisting - -A deposit sends **two transactions**: an ERC-20 `approve()` on the token contract, then the pool deposit call. Both contracts must be whitelisted in the session. If the deposit is rejected with a session permission error: - -```bash -# 1. Dry-run first — output includes both addresses under `transactions[0].to` (token) and `depositAddress` (pool) -polygon-agent deposit --asset USDC --amount 0.3 -# → note the token contract address (e.g. USDC: 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359) -# → note the depositAddress (e.g. Aave V3: 0x794a61358d6845594f94dc1db02a252b5b4814ad) - -# 2. Re-create wallet session with DeFi contracts whitelisted (covers both token and vault) -polygon-agent wallet create --defi - -# 3. Retry -polygon-agent deposit --asset USDC --amount 0.3 --broadcast -``` - -To add a contract not covered by `--defi`, use `--contract` alongside it: - -```bash -polygon-agent wallet create --defi --contract -``` - -### Yield Vault Contract Whitelist - -The following contracts are included when `--defi` is passed: - -#### Polygon Mainnet (chainId 137) - -| Protocol | Asset | Address | -|----------|-------|---------| -| Aave V3 Pool (all markets) | USDC, USDT, WETH, WMATIC… | `0x794a61358d6845594f94dc1db02a252b5b4814ad` | -| Morpho Compound USDC | USDC | `0x781fb7f6d845e3be129289833b04d43aa8558c42` | -| Morpho Compound WETH | WETH | `0xf5c81d25ee174d83f1fd202ca94ae6070d073ccf` | -| Morpho Compound POL | POL | `0x3f33f9f7e2d7cfbcbdf8ea8b870a6e3d449664c2` | +The embedded wallet can call the pool or vault on any chain, so no contract authorization is needed — just make sure the wallet holds a little POL or USDC on that chain for gas. To withdraw on a chain other than Polygon, pass `--chain mainnet` (or another supported chain) on the `withdraw` command itself. --- ## Full DeFi Flow Example ```bash -# 0. Create session with DeFi contracts whitelisted -polygon-agent wallet create --defi --usdc-limit 5 - # 1. Check balances polygon-agent balances @@ -219,21 +184,19 @@ polygon-agent swap --from USDC --to USDC --amount 0.5 --to-chain arbitrum --broa --- -## wallet create — Key Options +## Arbitrary Contract Calls -| Flag | Purpose | -|------|---------| -| `--defi` | Whitelist DeFi contracts (USDT, WETH, yield vaults on Polygon mainnet). Required for swaps and deposits. | -| `--usdc-limit ` | Enable USDC gas paymaster. Required when the wallet has no POL. Recommended: `--usdc-limit 5`. | -| `--force` | Replace an existing session without prompting. By default, re-creating a session is blocked if one already exists — the old wallet balance is not accessible from a new session. | -| `--contract ` | Whitelist an additional contract (repeatable). Use this if a deposit is rejected due to a missing contract permission. | +For any operation not covered by the dedicated commands, use `call` to send a raw transaction to any contract (the embedded wallet can call anything): ```bash -# New session for DeFi operations (swaps, deposits) with USDC gas paymaster -polygon-agent wallet create --defi --usdc-limit 5 +# Dry-run an arbitrary call +polygon-agent call --to 0x... --data 0x... + +# With an attached native value, then broadcast +polygon-agent call --to 0x... --data 0x... --value 0.1 --broadcast -# Replace an existing session -polygon-agent wallet create --defi --force --usdc-limit 5 +# For a native-only wallet, force the relayer to take its fee in POL +polygon-agent call --to 0x... --data 0x... --prefer-native-fee --broadcast ``` --- @@ -242,10 +205,9 @@ polygon-agent wallet create --defi --force --usdc-limit 5 | Error | Cause | Fix | |-------|-------|-----| +| `Not logged in` / no wallet found | No active wallet session | Run `polygon-agent wallet login` | +| Session expired | Sessions last about a week | Run `polygon-agent wallet login` | | `Insufficient : wallet has X` | Balance too low for the requested deposit amount | Run `polygon-agent balances` and adjust `--amount` | -| `Wallet has no POL for gas` | No native gas and no USDC paymaster | Fund with POL (`polygon-agent fund`) or re-create session with `--usdc-limit 5` | -| `Transaction rejected by relay` | Session permissions missing for pool or token contract | Re-create with `--defi` or add `--contract ` for a specific address | -| `Unable to pay gas` | No usable fee token found | Fund with POL or add `--usdc-limit 5` to session | -| `Wallet already exists` | Re-creating would orphan the old session | Use `--force` only after confirming old wallet funds are swept or unneeded | +| `Unable to pay gas` / `Wallet has no POL for gas` | Wallet can't cover the relayer fee in USDC or POL | Fund the wallet with a little POL or USDC; for a native-only wallet, pass `--prefer-native-fee` on `call` | | `Protocol X not yet supported` | Trails returned a protocol other than aave/morpho | Use `polygon-agent swap` to obtain the yield-bearing token manually | | `swap`: no route found | Insufficient liquidity for the pair | Try a different amount or token pair | diff --git a/packages/polygon-agent-cli/src/commands/agent-legacy.ts b/packages/polygon-agent-cli/src/commands/agent-legacy.ts index 9166eae..557b5d2 100644 --- a/packages/polygon-agent-cli/src/commands/agent-legacy.ts +++ b/packages/polygon-agent-cli/src/commands/agent-legacy.ts @@ -7,7 +7,7 @@ import { Contract, Interface, JsonRpcProvider } from 'ethers'; import IDENTITY_ABI from '../../contracts/IdentityRegistry.json' with { type: 'json' }; import REPUTATION_ABI from '../../contracts/ReputationRegistry.json' with { type: 'json' }; -import { runDappClientTx } from '../lib/dapp-client.ts'; +import { runTx as runDappClientTx } from '../lib/tx-dispatch.ts'; import { resolveNetwork, formatUnits, diff --git a/packages/polygon-agent-cli/src/commands/agent.ts b/packages/polygon-agent-cli/src/commands/agent.ts index aa93a86..2822e92 100644 --- a/packages/polygon-agent-cli/src/commands/agent.ts +++ b/packages/polygon-agent-cli/src/commands/agent.ts @@ -4,7 +4,7 @@ import { Contract, Interface, JsonRpcProvider } from 'ethers'; import IDENTITY_ABI from '../../contracts/IdentityRegistry.json' with { type: 'json' }; import REPUTATION_ABI from '../../contracts/ReputationRegistry.json' with { type: 'json' }; -import { runDappClientTx } from '../lib/dapp-client.ts'; +import { runTx as runDappClientTx } from '../lib/tx-dispatch.ts'; import { resolveNetwork, formatUnits, diff --git a/packages/polygon-agent-cli/src/commands/operations-ui.tsx b/packages/polygon-agent-cli/src/commands/operations-ui.tsx index 9c3a79a..b710c78 100644 --- a/packages/polygon-agent-cli/src/commands/operations-ui.tsx +++ b/packages/polygon-agent-cli/src/commands/operations-ui.tsx @@ -2,26 +2,15 @@ import { Box, Text, useApp } from 'ink'; import Spinner from 'ink-spinner'; import React, { useState, useEffect } from 'react'; -import { loadWalletSession } from '../lib/storage.ts'; +import type { ContractTokenBalance } from '@polygonlabs/oms-wallet'; + +import { findNetworkById } from '@polygonlabs/oms-wallet'; + +import { getOmsClient } from '../lib/oms-client.ts'; +import { loadOmsWalletPointer } from '../lib/storage.ts'; import { resolveNetwork, formatUnits } from '../lib/utils.ts'; import { Header, KV, Err, Divider, DryRunBanner, TxResult } from '../ui/components.js'; -// Get per-chain indexer URL -function getChainIndexerUrl(chainId: number): string { - const chainNames: Record = { - 137: 'polygon', - 80002: 'amoy', - 1: 'mainnet', - 42161: 'arbitrum', - 10: 'optimism', - 8453: 'base', - 43114: 'avalanche', - 56: 'bsc', - 100: 'gnosis' - }; - return `https://${chainNames[chainId] || 'polygon'}-indexer.sequence.app`; -} - function shortAddr(address: string, head = 6, tail = 4): string { return `${address.slice(0, head)}…${address.slice(-tail)}`; } @@ -52,44 +41,45 @@ export function BalancesUI({ walletName, chainOverride }: BalancesUIProps) { useEffect(() => { void (async () => { try { - const session = await loadWalletSession(walletName); - if (!session) throw new Error(`Wallet not found: ${walletName}`); + const pointer = await loadOmsWalletPointer(walletName); + if (!pointer) throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); + const addr = pointer.walletAddress; - const indexerKey = - process.env.SEQUENCE_INDEXER_ACCESS_KEY || - session.projectAccessKey || - process.env.SEQUENCE_PROJECT_ACCESS_KEY; - if (!indexerKey) - throw new Error('Missing project access key (set SEQUENCE_PROJECT_ACCESS_KEY)'); - - const network = resolveNetwork(chainOverride || session.chain || 'polygon'); + const network = resolveNetwork(chainOverride || 'polygon'); const nativeDecimals = network.nativeToken?.decimals ?? 18; const nativeSymbol = network.nativeToken?.symbol || 'POL'; - const { SequenceIndexer } = await import('@0xsequence/indexer'); - const indexer = new SequenceIndexer(getChainIndexerUrl(network.chainId), indexerKey); + const omsNetwork = findNetworkById(network.chainId); + if (!omsNetwork) throw new Error(`Unsupported chain for OMS indexer: ${network.chainId}`); + const oms = getOmsClient(walletName); - const [nativeRes, tokenRes] = await Promise.all([ - indexer.getNativeTokenBalance({ accountAddress: session.walletAddress }), - indexer.getTokenBalances({ accountAddress: session.walletAddress, includeMetadata: true }) - ]); + // SDK 0.1.0-alpha.4: one getBalances call returns native + tokens. + const res = await oms.indexer.getBalances({ + walletAddress: addr, + networks: [omsNetwork], + includeMetadata: true + }); const rows: BalanceEntry[] = [ { symbol: nativeSymbol, - balance: formatUnits(BigInt(nativeRes?.balance?.balance || '0'), nativeDecimals), + balance: formatUnits(BigInt(res.nativeBalances?.[0]?.balance || '0'), nativeDecimals), address: '(native)' } ]; - for (const b of tokenRes?.balances || []) { + for (const b of (res.balances || []) as ContractTokenBalance[]) { const sym = b.contractInfo?.symbol || 'ERC20'; const dec = b.contractInfo?.decimals ?? 18; - const addr = b.contractAddress ? shortAddr(b.contractAddress) : ''; - rows.push({ symbol: sym, balance: formatUnits(b.balance || '0', dec), address: addr }); + const tokenAddr = b.contractAddress ? shortAddr(b.contractAddress) : ''; + rows.push({ + symbol: sym, + balance: formatUnits(b.balance || '0', dec), + address: tokenAddr + }); } - setWalletAddress(session.walletAddress); + setWalletAddress(addr); setChainId(network.chainId); setChainName(network.name); setBalances(rows); @@ -262,9 +252,10 @@ export interface FundUIProps { walletAddress: string; chainId: number; fundingUrl: string; + funded?: boolean; } -export function FundUI({ walletName, walletAddress, chainId, fundingUrl }: FundUIProps) { +export function FundUI({ walletName, walletAddress, chainId, fundingUrl, funded }: FundUIProps) { const { exit } = useApp(); useEffect(() => { @@ -273,11 +264,12 @@ export function FundUI({ walletName, walletAddress, chainId, fundingUrl }: FundU return ( -
+
+ - open in browser to fund wallet + + {funded ? 'open your wallet dashboard' : 'open in browser to fund wallet'} + {fundingUrl} - swap any token to your wallet via Trails + + {funded + ? 'view balances and manage your wallet' + : 'add funds via card, exchange, or any token (Trails)'} + ); diff --git a/packages/polygon-agent-cli/src/commands/operations.ts b/packages/polygon-agent-cli/src/commands/operations.ts index c2b9b37..c9913e2 100644 --- a/packages/polygon-agent-cli/src/commands/operations.ts +++ b/packages/polygon-agent-cli/src/commands/operations.ts @@ -2,15 +2,21 @@ import type { CommandModule, Argv } from 'yargs'; import React from 'react'; -import { runDappClientTx } from '../lib/dapp-client.ts'; -import { loadWalletSession, loadBuilderConfig } from '../lib/storage.ts'; +import type { ContractTokenBalance } from '@polygonlabs/oms-wallet'; + +import { findNetworkById } from '@polygonlabs/oms-wallet'; + +import { isWalletFunded } from '../lib/indexer.ts'; +import { getOmsClient, loginUiBaseUrl } from '../lib/oms-client.ts'; +import { loadOmsWalletPointer, loadBuilderConfig } from '../lib/storage.ts'; import { resolveErc20BySymbol } from '../lib/token-directory.ts'; +import { runTx as runDappClientTx } from '../lib/tx-dispatch.ts'; import { resolveNetwork, formatUnits, parseUnits, getExplorerUrl, - getRpcUrl, + getReadRpcUrl, fileCoerce } from '../lib/utils.ts'; import { isTTY, inkRender } from '../ui/render.js'; @@ -39,22 +45,6 @@ function withBroadcast(yargs: Argv) { } // Get per-chain indexer URL -function getChainIndexerUrl(chainId: number): string { - const chainNames: Record = { - 137: 'polygon', - 80002: 'amoy', - 1: 'mainnet', - 42161: 'arbitrum', - 10: 'optimism', - 8453: 'base', - 43114: 'avalanche', - 56: 'bsc', - 100: 'gnosis' - }; - const name = chainNames[chainId] || 'polygon'; - return `https://${name}-indexer.sequence.app`; -} - // Load optional token map override from env function loadTokenMap(): Record> { const raw = process.env.TRAILS_TOKEN_MAP_JSON || ''; @@ -133,29 +123,27 @@ type BalanceRowJson = }; async function fetchBalancesRowsForChain( + walletName: string, walletAddress: string, - chainSpec: string, - indexerKey: string + chainSpec: string ): Promise<{ chainId: number; chain: string; balances: BalanceRowJson[] }> { const network = resolveNetwork(chainSpec); const nativeDecimals = network.nativeToken?.decimals ?? 18; const nativeSymbol = network.nativeToken?.symbol || 'POL'; - const { SequenceIndexer } = await import('@0xsequence/indexer'); - const indexerUrl = getChainIndexerUrl(network.chainId); - const indexer = new SequenceIndexer(indexerUrl, indexerKey); + const omsNetwork = findNetworkById(network.chainId); + if (!omsNetwork) throw new Error(`Unsupported chain for OMS indexer: ${network.chainId}`); + const oms = getOmsClient(walletName); - const [nativeRes, tokenRes] = await Promise.all([ - indexer.getNativeTokenBalance({ - accountAddress: walletAddress - }), - indexer.getTokenBalances({ - accountAddress: walletAddress, - includeMetadata: true - }) - ]); + // SDK 0.1.0-alpha.4 unified the two indexer calls into getBalances, returning + // { nativeBalances, balances } for the requested network(s). + const res = await oms.indexer.getBalances({ + walletAddress, + networks: [omsNetwork], + includeMetadata: true + }); - const nativeWei = nativeRes?.balance?.balance || '0'; + const nativeWei = res.nativeBalances?.[0]?.balance || '0'; const native: BalanceRowJson[] = [ { type: 'native', @@ -164,19 +152,15 @@ async function fetchBalancesRowsForChain( } ]; - const erc20: BalanceRowJson[] = (tokenRes?.balances || []).map( - (b: { - contractInfo?: { symbol?: string; name?: string; decimals?: number }; - contractAddress: string; - balance?: string; - }) => ({ + const erc20: BalanceRowJson[] = (res.balances || []) + .filter((b: ContractTokenBalance) => !!b.contractAddress) + .map((b: ContractTokenBalance) => ({ type: 'erc20' as const, symbol: b.contractInfo?.symbol || 'ERC20', name: b.contractInfo?.name || undefined, - contractAddress: b.contractAddress, + contractAddress: b.contractAddress as string, balance: formatUnits(b.balance || '0', b.contractInfo?.decimals ?? 18) - }) - ); + })); return { chainId: network.chainId, @@ -219,31 +203,22 @@ export const balancesCommand: CommandModule = { if (multiChainMode || (preferChainsArg && !isTTY())) { try { - const session = await loadWalletSession(walletName); - if (!session) { - throw new Error(`Wallet not found: ${walletName}`); - } - - const indexerKey = - process.env.SEQUENCE_INDEXER_ACCESS_KEY || - session.projectAccessKey || - process.env.SEQUENCE_PROJECT_ACCESS_KEY; - if (!indexerKey) { - throw new Error('Missing project access key (not in wallet session or environment)'); + const pointer = await loadOmsWalletPointer(walletName); + if (!pointer) { + throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); } + const walletAddress = pointer.walletAddress; if (multiChainMode) { const chainsOut = await Promise.all( - chainList.map((spec) => - fetchBalancesRowsForChain(session.walletAddress, spec, indexerKey) - ) + chainList.map((spec) => fetchBalancesRowsForChain(walletName, walletAddress, spec)) ); console.log( JSON.stringify( { ok: true, walletName, - walletAddress: session.walletAddress, + walletAddress, multiChain: true, chains: chainsOut }, @@ -252,17 +227,13 @@ export const balancesCommand: CommandModule = { ) ); } else { - const one = await fetchBalancesRowsForChain( - session.walletAddress, - singleChainSpec!, - indexerKey - ); + const one = await fetchBalancesRowsForChain(walletName, walletAddress, singleChainSpec!); console.log( JSON.stringify( { ok: true, walletName, - walletAddress: session.walletAddress, + walletAddress, chainId: one.chainId, chain: one.chain, balances: one.balances @@ -292,28 +263,20 @@ export const balancesCommand: CommandModule = { if (!isTTY()) { // Non-TTY: original JSON output (single default / --chain) try { - const session = await loadWalletSession(walletName); - if (!session) { - throw new Error(`Wallet not found: ${walletName}`); - } - - const indexerKey = - process.env.SEQUENCE_INDEXER_ACCESS_KEY || - session.projectAccessKey || - process.env.SEQUENCE_PROJECT_ACCESS_KEY; - if (!indexerKey) { - throw new Error('Missing project access key (not in wallet session or environment)'); + const pointer = await loadOmsWalletPointer(walletName); + if (!pointer) { + throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); } - const chainSpec = (argv.chain as string) || session.chain || 'polygon'; - const one = await fetchBalancesRowsForChain(session.walletAddress, chainSpec, indexerKey); + const chainSpec = (argv.chain as string) || 'polygon'; + const one = await fetchBalancesRowsForChain(walletName, pointer.walletAddress, chainSpec); console.log( JSON.stringify( { ok: true, walletName, - walletAddress: session.walletAddress, + walletAddress: pointer.walletAddress, chainId: one.chainId, chain: one.chain, balances: one.balances @@ -354,6 +317,79 @@ export const balancesCommand: CommandModule = { } }; +// The wallet funding page (Trails on-ramp + swap). Single source of truth so +// the `fund` command and the post-login step show the same thing: the +// agentconnect dashboard (same host as the login page), which reads +// ?wallet&chain&view. POLYGON_AGENT_FUNDING_UI overrides per environment. +function fundingUiBase(): string { + const v = process.env.POLYGON_AGENT_FUNDING_UI; + return v ? v.replace(/\/+$/, '') : loginUiBaseUrl(); +} + +/** + * Post-login funding step, balance-aware. Checks the wallet's USD balance via the + * OMS indexer and routes: funded (>0) -> dashboard, empty -> funding. On a + * human's machine (local, incl. under Claude Code / a harness) it opens the page; + * headless or --remote just returns the URL + balance on the CLI. Skipped by + * --no-fund. Falls back to wallet.polygon.technology if no hosted page is configured. + */ +export async function showFunding( + walletName: string, + walletAddress: string, + chainId = 137, + opts?: { openBrowser?: boolean; remote?: boolean } +): Promise { + const funded = await isWalletFunded(walletName, walletAddress, chainId); + const view = funded ? 'dashboard' : 'fund'; + + const base = fundingUiBase(); + const url = `${base}/?wallet=${walletAddress}&chain=${chainId}&view=${view}`; + + // Human path (local, incl. under Claude Code / a harness where stdout is piped + // so there is no TTY): open the page. Headless or --remote (browser elsewhere): + // skip it and surface the URL + balance on the CLI. open() no-ops/throws on a + // GUI-less host, so attempting it is safe. + if (opts?.openBrowser && !opts?.remote) { + try { + const { default: open } = await import('open'); + await open(url); + } catch { + // open() can fail on a headless host — the URL/panel below is the fallback. + } + } + + if (isTTY()) { + await inkRender( + React.createElement(FundUI, { + walletName, + walletAddress, + chainId, + fundingUrl: url, + funded + }) + ); + } else { + console.log( + JSON.stringify( + { + ok: true, + walletName, + walletAddress, + chainId, + funded, + view, + url, + message: funded + ? `Wallet ${walletAddress} is funded. Dashboard: ${url}` + : `Fund wallet ${walletAddress} (no balance yet). Add funds: ${url}` + }, + null, + 2 + ) + ); + } +} + // --- fund --- export const fundCommand: CommandModule = { command: 'fund', @@ -363,35 +399,12 @@ export const fundCommand: CommandModule = { const walletName = argv.wallet as string; try { - const session = await loadWalletSession(walletName); + const session = await loadOmsWalletPointer(walletName); if (!session) { - throw new Error(`Wallet not found: ${walletName}. Run 'wallet create' first.`); + throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); } - const walletAddress = session.walletAddress; - const chainId = session.chainId || 137; - const fundingUrl = `https://wallet.polygon.technology`; - - if (isTTY()) { - await inkRender( - React.createElement(FundUI, { walletName, walletAddress, chainId, fundingUrl }) - ); - } else { - console.log( - JSON.stringify( - { - ok: true, - walletName, - walletAddress, - chainId, - fundingUrl, - message: `Visit ${fundingUrl} to fund your wallet (${walletAddress}).` - }, - null, - 2 - ) - ); - } + await showFunding(walletName, session.walletAddress, 137, { openBrowser: true }); } catch (error) { console.error( JSON.stringify( @@ -503,10 +516,10 @@ async function handleSendNative(argv: { explorerUrl?: string; walletAddress?: string; }> { - const session = await loadWalletSession(walletName); - if (!session) throw new Error(`Wallet not found: ${walletName}`); + const session = await loadOmsWalletPointer(walletName); + if (!session) throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); - const network = resolveNetwork((argv.chain as string) || session.chain || 'polygon'); + const network = resolveNetwork((argv.chain as string) || 'polygon'); const decimals = network.nativeToken?.decimals ?? 18; const value = parseUnits(amount, decimals); @@ -539,10 +552,10 @@ async function handleSendNative(argv: { if (!isTTY()) { // Non-TTY: original JSON output try { - const session = await loadWalletSession(walletName); - if (!session) throw new Error(`Wallet not found: ${walletName}`); + const session = await loadOmsWalletPointer(walletName); + if (!session) throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); - const network = resolveNetwork((argv.chain as string) || session.chain || 'polygon'); + const network = resolveNetwork((argv.chain as string) || 'polygon'); const decimals = network.nativeToken?.decimals ?? 18; const value = parseUnits(amount, decimals); @@ -607,8 +620,7 @@ async function handleSendNative(argv: { // TTY: Ink UI let failed = false; try { - const session = await loadWalletSession(walletName); - const network = resolveNetwork((argv.chain as string) || session?.chain || 'polygon'); + const network = resolveNetwork((argv.chain as string) || 'polygon'); const nativeSymbol = network.nativeToken?.symbol || 'POL'; await inkRender( @@ -691,10 +703,10 @@ async function handleSendToken(argv: { resolvedSymbol: string; network: ReturnType; }> { - const session = await loadWalletSession(walletName); - if (!session) throw new Error(`Wallet not found: ${walletName}`); + const session = await loadOmsWalletPointer(walletName); + if (!session) throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); - const network = resolveNetwork((argv.chain as string) || session.chain || 'polygon'); + const network = resolveNetwork((argv.chain as string) || 'polygon'); let token = tokenAddress; let decimals = decimalsArg ?? null; let resolvedSymbol = symbolArg || 'TOKEN'; @@ -838,10 +850,10 @@ async function handleCall(argv: { throw new Error('--data must be 0x-prefixed hex (use viem/ethers/cast to encode)'); } - const session = await loadWalletSession(walletName); - if (!session) throw new Error(`Wallet not found: ${walletName}`); + const session = await loadOmsWalletPointer(walletName); + if (!session) throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); - const network = resolveNetwork(argv.chain || session.chain || 'polygon'); + const network = resolveNetwork(argv.chain || 'polygon'); const decimals = network.nativeToken?.decimals ?? 18; const value = argv.value ? parseUnits(argv.value, decimals) : 0n; @@ -951,12 +963,12 @@ export const swapCommand: CommandModule = { const broadcast = argv.broadcast as boolean; try { - const session = await loadWalletSession(walletName); + const session = await loadOmsWalletPointer(walletName); if (!session) { - throw new Error(`Wallet not found: ${walletName}`); + throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); } - const originNetwork = resolveNetwork((argv.chain as string) || session.chain || 'polygon'); + const originNetwork = resolveNetwork((argv.chain as string) || 'polygon'); const originChainId = originNetwork.chainId; const originNativeSymbol = originNetwork.nativeToken?.symbol || 'NATIVE'; @@ -987,7 +999,10 @@ export const swapCommand: CommandModule = { const { TrailsApi, TradeType } = await import('@0xtrails/api'); const trailsApiKey = - process.env.TRAILS_API_KEY || (await loadBuilderConfig())?.accessKey || ''; + process.env.TRAILS_API_KEY || + process.env.SEQUENCE_PROJECT_ACCESS_KEY || + (await loadBuilderConfig())?.accessKey || + ''; const trails = new TrailsApi(trailsApiKey, { hostname: process.env.TRAILS_API_HOSTNAME }); @@ -1176,10 +1191,10 @@ export const depositCommand: CommandModule = { const broadcast = argv.broadcast as boolean; try { - const session = await loadWalletSession(walletName); - if (!session) throw new Error(`Wallet not found: ${walletName}`); + const session = await loadOmsWalletPointer(walletName); + if (!session) throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); - const network = resolveNetwork((argv.chain as string) || session.chain || 'polygon'); + const network = resolveNetwork((argv.chain as string) || 'polygon'); const { chainId } = network; const walletAddress = session.walletAddress; @@ -1194,7 +1209,10 @@ export const depositCommand: CommandModule = { const { TrailsApi } = await import('@0xtrails/api'); const trailsApiKey = - process.env.TRAILS_API_KEY || (await loadBuilderConfig())?.accessKey || ''; + process.env.TRAILS_API_KEY || + process.env.SEQUENCE_PROJECT_ACCESS_KEY || + (await loadBuilderConfig())?.accessKey || + ''; const trails = new TrailsApi(trailsApiKey, { hostname: process.env.TRAILS_API_HOSTNAME }); @@ -1218,8 +1236,8 @@ export const depositCommand: CommandModule = { throw new Error( `No active ${assetSymbol} earn pools found on ${network.name}` + (protocolFilter ? ` (protocol: ${protocolFilter})` : '') + - `. Confirm wallet state: polygon-agent balances. ` + - `Alternative: polygon-agent swap --from ${assetSymbol} --to .` + `. Confirm wallet state: agent balances. ` + + `Alternative: agent swap --from ${assetSymbol} --to .` ); } @@ -1255,7 +1273,7 @@ export const depositCommand: CommandModule = { const available = viemFormatUnits(usdcBal, asset.decimals); throw new Error( `Insufficient ${assetSymbol}: wallet has ${available} ${assetSymbol}, deposit requires ${amountArg}. ` + - `Run: polygon-agent balances` + `Run: agent balances` ); } if (nativeBal < POL_GAS_RESERVE && requestedUnits + USDC_GAS_RESERVE > usdcBal) { @@ -1264,7 +1282,7 @@ export const depositCommand: CommandModule = { if (adjusted <= 0n) { throw new Error( `Insufficient ${assetSymbol} for deposit plus 0.1 gas reserve. ` + - `Fund with at least 0.1 POL for native gas or ensure USDC balance exceeds deposit by 0.1: polygon-agent fund` + `Fund with at least 0.1 POL for native gas or ensure USDC balance exceeds deposit by 0.1: agent fund` ); } amountArg = viemFormatUnits(adjusted, asset.decimals); @@ -1366,7 +1384,7 @@ export const depositCommand: CommandModule = { } else { throw new Error( `Protocol "${pool.protocol}" from Trails is not yet supported for direct deposit encoding. ` + - `Supported: aave, morpho. Open an issue or use 'polygon-agent swap' to obtain the yield-bearing token.` + `Supported: aave, morpho. Open an issue or use 'agent swap' to obtain the yield-bearing token.` ); } @@ -1388,7 +1406,7 @@ export const depositCommand: CommandModule = { chainId, chain: network.name, transactions, - note: `Re-run with --broadcast to submit the deposit. If session rejects the call, re-create with: polygon-agent wallet create --contract ${asset.address} --contract ${pool.depositAddress}` + note: `Submits as two transactions (approve + supply) — non-atomic. Re-run with --broadcast to submit. Ensure the wallet holds ${assetSymbol} plus a little POL or USDC for gas.` }, bigintReplacer, 2 @@ -1397,45 +1415,14 @@ export const depositCommand: CommandModule = { return; } - let result; - try { - result = await runDappClientTx({ - walletName, - chainId, - transactions, - broadcast, - preferNativeFee: false - }); - } catch (txErr) { - const txMsg = (txErr as Error).message || ''; - if (txMsg.includes('No signer supported')) { - throw new Error( - `Session does not permit calls to ${pool.depositAddress} (${pool.protocol} pool) or ${asset.address} (${assetSymbol} approve). ` + - `Re-create the wallet session with: polygon-agent wallet create --contract ${asset.address} --contract ${pool.depositAddress}\n` + - `Original error: ${txMsg}` - ); - } - if (txMsg.includes('Identity signers not found') || txMsg.includes('signers not found')) { - throw new Error( - `Wallet has no POL for gas and no USDC paymaster is configured. ` + - `Fund with POL: polygon-agent fund\n` + - `Or enable USDC gas: polygon-agent wallet create --usdc-limit 5\n` + - `Original error: ${txMsg}` - ); - } - if ( - txMsg.includes('Request aborted') || - txMsg.includes('AbortedError') || - txMsg.includes('code 1005') - ) { - throw new Error( - `Transaction rejected by relay — likely a session permission issue. ` + - `Re-create the wallet session: polygon-agent wallet create --contract ${asset.address} --contract ${pool.depositAddress}\n` + - `Original error: ${txMsg}` - ); - } - throw txErr; - } + // NON-ATOMIC: deposit submits approve + supply sequentially via runOmsTx. + const result = await runDappClientTx({ + walletName, + chainId, + transactions, + broadcast, + preferNativeFee: false + }); console.log( JSON.stringify( @@ -1638,10 +1625,10 @@ export const withdrawCommand: CommandModule = { const assetSymbol = (argv.asset as string)?.toUpperCase(); try { - const session = await loadWalletSession(walletName); - if (!session) throw new Error(`Wallet not found: ${walletName}`); + const session = await loadOmsWalletPointer(walletName); + if (!session) throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); - const network = resolveNetwork((argv.chain as string) || session.chain || 'polygon'); + const network = resolveNetwork((argv.chain as string) || 'polygon'); const { chainId } = network; const walletAddress = session.walletAddress as `0x${string}`; @@ -1650,7 +1637,7 @@ export const withdrawCommand: CommandModule = { const viemChain = await viemChainForWithdraw(chainId); const publicClient = createPublicClient({ chain: viemChain, - transport: http(getRpcUrl(network)) + transport: http(getReadRpcUrl(network)) }); let positionAddr = String(argv.position || '') @@ -1667,8 +1654,8 @@ export const withdrawCommand: CommandModule = { const { TrailsApi } = await import('@0xtrails/api'); const trailsApiKey = process.env.TRAILS_API_KEY || - session.projectAccessKey || process.env.SEQUENCE_PROJECT_ACCESS_KEY || + (await loadBuilderConfig())?.accessKey || ''; const trails = new TrailsApi(trailsApiKey, { hostname: process.env.TRAILS_API_HOSTNAME @@ -1897,8 +1884,6 @@ export const withdrawCommand: CommandModule = { }; } - const targetContract = kind === 'aave' ? (summary.poolAddress as string) : positionAddr; - if (!broadcast) { console.log( JSON.stringify( @@ -1912,7 +1897,7 @@ export const withdrawCommand: CommandModule = { kind, ...summary, transactions, - note: `Re-run with --broadcast to submit. If the session rejects the call, re-create the wallet with the pool/vault whitelisted: polygon-agent wallet create --contract ${targetContract}` + note: `Re-run with --broadcast to submit. Ensure the wallet holds a little POL or USDC for gas.` }, bigintReplacer, 2 @@ -1921,25 +1906,13 @@ export const withdrawCommand: CommandModule = { return; } - let result; - try { - result = await runDappClientTx({ - walletName, - chainId, - transactions, - broadcast, - preferNativeFee: false - }); - } catch (txErr) { - if ((txErr as Error).message?.includes('No signer supported')) { - throw new Error( - `Session does not permit calls to ${targetContract}. ` + - `Re-create the wallet session with: polygon-agent wallet create --contract ${targetContract}\n` + - `Original error: ${(txErr as Error).message}` - ); - } - throw txErr; - } + const result = await runDappClientTx({ + walletName, + chainId, + transactions, + broadcast, + preferNativeFee: false + }); console.log( JSON.stringify( @@ -2011,12 +1984,11 @@ export const x402PayCommand: CommandModule = { try { const [session, builderConfig] = await Promise.all([ - loadWalletSession(walletName), + loadOmsWalletPointer(walletName), loadBuilderConfig() ]); - if (!session) throw new Error(`Wallet not found: ${walletName}`); - if (!builderConfig?.privateKey) - throw new Error('Builder EOA not found. Run: polygon-agent setup'); + if (!session) throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); + if (!builderConfig?.privateKey) throw new Error('Builder EOA not found. Run: agent setup'); const { privateKeyToAccount } = await import('viem/accounts'); const { wrapFetchWithPayment, x402Client, x402HTTPClient, decodePaymentResponseHeader } = @@ -2136,7 +2108,7 @@ export const x402PayCommand: CommandModule = { process.stderr.write('Waiting for confirmation...\n'); const rpcUrl = process.env.SEQUENCE_NODES_URL?.replace('{network}', payChain) || - `https://nodes.sequence.app/${payChain}/${session.projectAccessKey || process.env.SEQUENCE_PROJECT_ACCESS_KEY || ''}`; + getReadRpcUrl(resolveNetwork(String(payChainId))); for (let attempt = 0; attempt < 30; attempt++) { await new Promise((r) => setTimeout(r, 3000)); try { @@ -2202,18 +2174,56 @@ export const x402PayCommand: CommandModule = { (n: string) => probe.headers.get(n), {} ); - const req = paymentRequired.accepts[0]; + // Providers may advertise many payment options across chains — testnets + // and non-standard batched/gateway schemes included — and accepts[0] is + // not necessarily Polygon (QuickNode, e.g., lists Base Sepolia first). + // Select the cheapest plain-USDC transfer on the preferred chain (default + // Polygon 137, or --chain) so we pay ~$0.001 on Polygon, not whatever is + // first. The same selector is handed to the payment client below so the + // funded amount/asset/chain match what actually gets paid. + const chainArg = argv.chain as string | undefined; + let preferredChainId = 137; + if (chainArg) { + try { + preferredChainId = resolveNetwork(chainArg).chainId; + } catch { + preferredChainId = 137; + } + } + // A plain EIP-3009 transfer (what ExactEvmScheme signs), not a batched / + // gateway-wallet scheme that uses a different signing domain. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const isPlainTransfer = (r: any): boolean => { + const name = String(r?.extra?.name || '').toLowerCase(); + return !name.includes('gateway') && !name.includes('batched'); + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const cheapest = (list: any[]): any => + [...list].sort((a, b) => (BigInt(a.amount) < BigInt(b.amount) ? -1 : 1))[0]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const selectAccept = (_version: number, accepts: any[]): any => { + const evm = (accepts || []).filter( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (r: any) => typeof r?.network === 'string' && r.network.startsWith('eip155:') + ); + const preferred = evm.filter((r) => r.network === `eip155:${preferredChainId}`); + const preferredPlain = preferred.filter(isPlainTransfer); + const evmPlain = evm.filter(isPlainTransfer); + if (preferredPlain.length) return cheapest(preferredPlain); + if (preferred.length) return cheapest(preferred); + if (evmPlain.length) return cheapest(evmPlain); + return accepts?.[0]; + }; + + const req = selectAccept(paymentRequired.x402Version ?? 2, paymentRequired.accepts); if (!req) throw new Error('No payment requirements in 402 response'); const { amount, asset, network: paymentNetwork } = req; - const chainArg = argv.chain as string | undefined; const chainFromPayment = paymentNetwork?.startsWith('eip155:') ? paymentNetwork.split(':')[1] : null; - const resolvedNetwork = resolveNetwork( - chainArg || chainFromPayment || session.chain || 'polygon' - ); + const resolvedNetwork = resolveNetwork(chainArg || chainFromPayment || 'polygon'); const pad = (hex: string, n = 64) => String(hex).replace(/^0x/, '').padStart(n, '0'); const transferData = '0xa9059cbb' + pad(eoaAccount.address) + pad('0x' + BigInt(amount).toString(16)); @@ -2230,14 +2240,22 @@ export const x402PayCommand: CommandModule = { }); process.stderr.write(`Funded via tx: ${fundResult.txHash}\n`); - const client = new x402Client(); + const client = new x402Client(selectAccept); // eslint-disable-next-line @typescript-eslint/no-explicit-any client.register('eip155:*', new ExactEvmScheme(eoaAccount as any)); const fetchWithPayment = wrapFetchWithPayment(fetch, client); + // Ensure a JSON body is parseable upstream: set Content-Type when a body is + // present and the caller didn't specify one (mirrors the bazaar path). + // Without this, proxied POST services reject the body ("expected object"). + const retryHeaders: Record = { ...headers }; + if (body && !Object.keys(retryHeaders).some((h) => h.toLowerCase() === 'content-type')) { + retryHeaders['Content-Type'] = 'application/json'; + } + const response = await fetchWithPayment(url, { method, - headers: Object.keys(headers).length ? headers : undefined, + headers: Object.keys(retryHeaders).length ? retryHeaders : undefined, body: body || undefined }); diff --git a/packages/polygon-agent-cli/src/commands/polymarket.ts b/packages/polygon-agent-cli/src/commands/polymarket.ts index d792da3..34dd4f1 100644 --- a/packages/polygon-agent-cli/src/commands/polymarket.ts +++ b/packages/polygon-agent-cli/src/commands/polymarket.ts @@ -1,12 +1,11 @@ // Polymarket CLI commands -// Architecture: Sequence smart wallet → Polymarket proxy wallet → CLOB +// Architecture: OMS smart wallet → Polymarket proxy wallet → CLOB // - `approve`: sets on-chain approvals on proxy wallet (one-time) // - `clob-buy`: funds proxy wallet from smart wallet, then places CLOB BUY order // - CLOB orders: maker=proxyWallet, signer=EOA, signatureType=POLY_PROXY import type { CommandModule } from 'yargs'; -import { runDappClientTx } from '../lib/dapp-client.ts'; import { getMarkets, getMarket, @@ -25,7 +24,8 @@ import { NEG_RISK_ADAPTER, COLLATERAL_ONRAMP } from '../lib/polymarket.ts'; -import { loadWalletSession, savePolymarketKey, loadPolymarketKey } from '../lib/storage.ts'; +import { loadOmsWalletPointer, savePolymarketKey, loadPolymarketKey } from '../lib/storage.ts'; +import { runTx as runDappClientTx } from '../lib/tx-dispatch.ts'; // ─── handlers ──────────────────────────────────────────────────────────────── @@ -321,10 +321,10 @@ async function handleClobBuy(argv: { } const [session, privateKey] = await Promise.all([ - loadWalletSession(walletName), + loadOmsWalletPointer(walletName), loadPolymarketKey() ]); - if (!session) throw new Error(`Wallet not found: ${walletName}`); + if (!session) throw new Error(`Wallet not found: ${walletName}. Run: agent wallet login`); const { privateKeyToAccount } = await import('viem/accounts'); const account = privateKeyToAccount(privateKey as `0x${string}`); diff --git a/packages/polygon-agent-cli/src/commands/setup-ui.tsx b/packages/polygon-agent-cli/src/commands/setup-ui.tsx index 6d79a7d..59ae515 100644 --- a/packages/polygon-agent-cli/src/commands/setup-ui.tsx +++ b/packages/polygon-agent-cli/src/commands/setup-ui.tsx @@ -2,94 +2,13 @@ import { ethers } from 'ethers'; import { Box, Text, useApp } from 'ink'; import React, { useState, useEffect } from 'react'; +import { getAuthToken, createProject, getDefaultAccessKey } from '../lib/builder-api.ts'; import { generateEthAuthProof } from '../lib/ethauth.ts'; import { saveBuilderConfig, loadBuilderConfig } from '../lib/storage.ts'; import { Header, Step, KV, Hint, Err } from '../ui/components.js'; // Re-export API helpers used by setup.ts -export async function getAuthToken(proofString: string): Promise { - const apiUrl = process.env.SEQUENCE_BUILDER_API_URL || 'https://api.sequence.build'; - const url = `${apiUrl}/rpc/Builder/GetAuthToken`; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ ethauthProof: proofString }) - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`GetAuthToken failed: ${response.status} ${errorText}`); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const data: any = await response.json(); - - if (!data.ok || !data.auth?.jwtToken) { - throw new Error('GetAuthToken returned invalid response'); - } - - return data.auth.jwtToken; -} - -export async function createProject( - name: string, - jwtToken: string -): Promise<{ id: number; name: string }> { - const apiUrl = process.env.SEQUENCE_BUILDER_API_URL || 'https://api.sequence.build'; - const url = `${apiUrl}/rpc/Builder/CreateProject`; - - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${jwtToken}` - }, - body: JSON.stringify({ name }) - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`CreateProject failed: ${response.status} ${errorText}`); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const data: any = await response.json(); - - if (!data.project) { - throw new Error('CreateProject returned invalid response'); - } - - return data.project; -} - -export async function getDefaultAccessKey(projectId: number, jwtToken: string): Promise { - const apiUrl = process.env.SEQUENCE_BUILDER_API_URL || 'https://api.sequence.build'; - const url = `${apiUrl}/rpc/QuotaControl/GetDefaultAccessKey`; - - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${jwtToken}` - }, - body: JSON.stringify({ projectID: projectId }) - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`GetDefaultAccessKey failed: ${response.status} ${errorText}`); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const data: any = await response.json(); - - if (!data.accessKey?.accessKey) { - throw new Error('GetDefaultAccessKey returned invalid response'); - } - - return data.accessKey.accessKey; -} +export { getAuthToken, createProject, getDefaultAccessKey } from '../lib/builder-api.ts'; type Phase = | 'checking' @@ -186,14 +105,14 @@ export function SetupUI({ name, force }: { name: string; force: boolean }) { - Next: polygon-agent wallet create + Next: agent wallet login )} {phase === 'existing' && result && ( Already configured - Next: polygon-agent wallet create + Next: agent wallet login )} {phase === 'error' && } diff --git a/packages/polygon-agent-cli/src/commands/setup.ts b/packages/polygon-agent-cli/src/commands/setup.ts index d7c37b5..c4a049d 100644 --- a/packages/polygon-agent-cli/src/commands/setup.ts +++ b/packages/polygon-agent-cli/src/commands/setup.ts @@ -3,15 +3,18 @@ import type { CommandModule } from 'yargs'; import { ethers } from 'ethers'; import React from 'react'; +import { getAuthToken, createProject, getDefaultAccessKey } from '../lib/builder-api.ts'; import { generateEthAuthProof } from '../lib/ethauth.ts'; -import { saveBuilderConfig, loadBuilderConfig } from '../lib/storage.ts'; +import { saveBuilderConfig, loadBuilderConfig, saveOmsConfig } from '../lib/storage.ts'; import { generateAgentName } from '../lib/utils.ts'; import { isTTY, inkRender } from '../ui/render.js'; -import { SetupUI, getAuthToken, createProject, getDefaultAccessKey } from './setup-ui.js'; +import { SetupUI } from './setup-ui.js'; interface SetupArgs { name?: string; force?: boolean; + 'oms-publishable-key'?: string; + 'oms-project-id'?: string; } export const setupCommand: CommandModule = { @@ -27,10 +30,41 @@ export const setupCommand: CommandModule = { type: 'boolean', describe: 'Recreate even if already configured', default: false + }) + .option('oms-publishable-key', { + type: 'string', + describe: 'OMS (Open Money Stack) publishable key (from the OMS Builder dashboard)' + }) + .option('oms-project-id', { + type: 'string', + describe: 'OMS project id (e.g. proj_...) — optional, legacy display field only' }), handler: async (argv) => { const name = argv.name || generateAgentName(); + // If an OMS publishable key is supplied, persist it (independent of the legacy + // builder/access-key flow). Used by the V3 `wallet login` path. The project id + // is optional legacy metadata — the SDK identifies the project from the + // publishable key alone. + const omsPk = argv['oms-publishable-key']; + const omsProj = argv['oms-project-id']; + if (omsPk) { + await saveOmsConfig({ publishableKey: omsPk, omsProjectId: omsProj }); + if (!isTTY()) { + console.log( + JSON.stringify( + { + ok: true, + message: 'OMS credentials saved to ~/.polygon-agent/builder.json' + }, + null, + 2 + ) + ); + return; + } + } + if (!isTTY()) { // Non-TTY fallback: original JSON output try { diff --git a/packages/polygon-agent-cli/src/commands/wallet-ui.tsx b/packages/polygon-agent-cli/src/commands/wallet-ui.tsx index fbc8d63..6738316 100644 --- a/packages/polygon-agent-cli/src/commands/wallet-ui.tsx +++ b/packages/polygon-agent-cli/src/commands/wallet-ui.tsx @@ -1,457 +1,8 @@ -import { Box, Text, useApp, useInput } from 'ink'; -import Spinner from 'ink-spinner'; -import React, { useState, useEffect, useRef } from 'react'; +import { Box, Text } from 'ink'; +import React from 'react'; -import { - generateX25519Keypair, - bytesToHex, - computeCodeHash, - decryptSession -} from '@polygonlabs/agent-shared'; +import { Header, Addr, KV } from '../ui/components.js'; -import { RelayClient, RelayCodeError } from '../lib/relay-client.ts'; -import { - saveWalletSession, - saveWalletRequest, - deleteWalletRequest, - sessionPayloadToWalletSession -} from '../lib/storage.ts'; -import { normalizeChain, resolveNetwork, formatUnits } from '../lib/utils.ts'; -import { Header, Step, UrlBox, Addr, CodeDisplay, Hint, Err, KV } from '../ui/components.js'; - -// Session permission args interface (subset used for URL building) -interface SessionPermissionArgs { - 'native-limit'?: string; - 'usdc-limit'?: string; - 'usdt-limit'?: string; - 'token-limit'?: string[]; - contract?: string[]; - 'usdc-to'?: string; - 'usdc-amount'?: string; - 'access-key'?: string; -} - -const AUTO_WHITELISTED_CONTRACTS = [ - '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432', // ERC-8004 IdentityRegistry - '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63', // ERC-8004 ReputationRegistry - '0xABAAd93EeE2a569cF0632f39B10A9f5D734777ca', // ValueForwarder (required for send native POL) - - // Polygon mainnet (chainId 137) — ERC-20 token contracts (needed for approve() in deposits/swaps) - '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', // USDC (native) - '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', // USDT - '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', // WETH - - // Polygon mainnet (chainId 137) — yield vaults - '0x794a61358d6845594f94dc1db02a252b5b4814ad', // Aave V3 Pool (all markets) - '0x781fb7f6d845e3be129289833b04d43aa8558c42', // Morpho Compound USDC - '0xf5c81d25ee174d83f1fd202ca94ae6070d073ccf', // Morpho Compound WETH - '0x3f33f9f7e2d7cfbcbdf8ea8b870a6e3d449664c2', // Morpho Compound POL - - // Katana (chainId 747474) — Morpho vaults - '0x1ecdc3f2b5e90bfb55ff45a7476ff98a8957388e', // Gauntlet USDT (~$97M TVL) - '0x61d4f9d3797ba4da152238c53a6f93fb665c3c1d', // Steakhouse Prime USDC (~$54M TVL) - '0xfade0c546f44e33c134c4036207b314ac643dc2e', // Yearn OG ETH (~$16M TVL) - '0xce2b8e464fc7b5e58710c24b7e5ebfb6027f29d7', // Yearn OG USDC (~$16M TVL) - '0xe4248e2105508fcbad3fe95691551d1af14015f7', // Gauntlet USDC (~$8M TVL) - '0x8ed68f91afbe5871dce31ae007a936ebe8511d47', // Yearn OG USDT (~$8M TVL) - '0xc5e7ab07030305fc925175b25b93b285d40dcdff', // Gauntlet WETH (~$6M TVL) - '0xef77f8c53af95f3348cee0fb2a02ee02ab9cdca5' // Hyperithm vbUSDC Apex (~$3M TVL) -]; - -function applySessionPermissionParams(url: URL, argv: SessionPermissionArgs): void { - const usdcTo = argv['usdc-to']; - const usdcAmount = argv['usdc-amount']; - if (usdcTo || usdcAmount) { - if (!usdcTo || !usdcAmount) throw new Error('Must provide both --usdc-to and --usdc-amount'); - url.searchParams.set('erc20', 'usdc'); - url.searchParams.set('erc20To', usdcTo); - url.searchParams.set('erc20Amount', usdcAmount); - } - - const nativeLimit = argv['native-limit']; - const usdcLimit = argv['usdc-limit'] || '50'; - const usdtLimit = argv['usdt-limit']; - if (nativeLimit) url.searchParams.set('nativeLimit', nativeLimit); - url.searchParams.set('usdcLimit', usdcLimit); - if (usdtLimit) url.searchParams.set('usdtLimit', usdtLimit); - - const tokenLimits = (argv['token-limit'] || []) - .map((s) => String(s || '').trim()) - .filter(Boolean); - if (tokenLimits.length) url.searchParams.set('tokenLimits', tokenLimits.join(',')); - - const userContracts = (argv.contract || []).map((s) => String(s || '').trim()).filter(Boolean); - const allContracts = [...new Set([...AUTO_WHITELISTED_CONTRACTS, ...userContracts])]; - url.searchParams.set('contracts', allContracts.join(',')); -} - -export type WalletCreatePhase = - | 'registering' - | 'waiting' - | 'code' - | 'nocode' - | 'linking' - | 'done' - | 'balances' - | 'error'; - -interface BalanceRow { - symbol: string; - balance: string; - usd?: string; -} - -export interface WalletCreateUIProps { - name: string; - chain: string; - timeout: number; - argv: SessionPermissionArgs & { 'access-key'?: string }; - tty?: boolean; - onComplete?: (walletAddress: string, chainId: number, chain: string) => void; - onError?: (message: string) => void; -} - -// Renders nothing but registers Ink's keystroke listener so the user can type -// the 6-digit approval code. Extracted so it can be conditionally mounted — -// useInput() triggers raw-mode setup on stdin which crashes in non-TTY contexts. -function CodeInputCapture({ - phase, - setCode -}: { - phase: WalletCreatePhase; - setCode: React.Dispatch>; -}) { - useInput((input, key) => { - if (phase !== 'code') return; - if (/^\d+$/.test(input)) { - setCode((prev) => (prev + input).slice(0, 6)); - } - if (key.backspace || key.delete) { - setCode((prev) => prev.slice(0, -1)); - } - }); - return null; -} - -export function WalletCreateUI({ - name, - chain, - timeout, - argv, - tty = true, - onComplete, - onError -}: WalletCreateUIProps) { - const { exit } = useApp(); - const [phase, setPhase] = useState('registering'); - const [url, setUrl] = useState(''); - const [rid, setRid] = useState(''); - const [address, setAddress] = useState(''); - const [walletChain, setWalletChain] = useState(''); - const [code, setCode] = useState(''); - const [codeError, setCodeError] = useState(''); - const [error, setError] = useState(''); - const [balances, setBalances] = useState([]); - const stateRef = useRef<{ rid: string; cliSk: Uint8Array; relay: RelayClient } | null>(null); - const submittingRef = useRef(false); - - useEffect(() => { - void (async () => { - try { - const normalizedChain = normalizeChain(chain); - const connectorBase = ( - process.env.SEQUENCE_ECOSYSTEM_CONNECTOR_URL || 'https://agentconnect.polygon.technology' - ).replace(/\/$/, ''); - - const { secretKey: cliSk, publicKey: cliPk } = generateX25519Keypair(); - const cliPkHex = bytesToHex(cliPk); - const cliSkHex = bytesToHex(cliSk); - - const relay = new RelayClient(connectorBase); - const rid = await relay.createRequest(cliPkHex); - - const projectAccessKey = argv['access-key'] || process.env.SEQUENCE_PROJECT_ACCESS_KEY; - - const createdAt = new Date().toISOString(); - const expiresAt = new Date(Date.now() + 10 * 60 * 1000).toISOString(); - - await saveWalletRequest(rid, { - rid, - walletName: name, - chain: normalizedChain, - createdAt, - expiresAt, - publicKeyB64u: '', - privateKeyB64u: '', - projectAccessKey: projectAccessKey || null, - cliSkHex - }); - - const urlObj = new URL(`${connectorBase}/link`); - urlObj.searchParams.set('rid', rid); - urlObj.searchParams.set('wallet', name); - urlObj.searchParams.set('chain', normalizedChain); - if (projectAccessKey) urlObj.searchParams.set('accessKey', projectAccessKey); - applySessionPermissionParams(urlObj, argv); - const fullUrl = urlObj.toString(); - - stateRef.current = { rid, cliSk, relay }; - setUrl(fullUrl); - setRid(rid); - setPhase('waiting'); - - try { - const { default: open } = await import('open'); - await open(fullUrl); - } catch { - // ignore - } - - await relay.waitForReady(rid, timeout * 1000, 2_000); - // Non-TTY: can't collect code interactively — show import command and exit - if (!tty) { - setPhase('nocode'); - exit(); - return; - } - setPhase('code'); - } catch (e: unknown) { - const msg = e instanceof Error ? e.message : String(e); - setError(msg); - setPhase('error'); - onError?.(msg); - exit(new Error(msg)); - } - })(); - }, []); - - useEffect(() => { - if (phase === 'code' && code.length === 6 && !submittingRef.current) { - submittingRef.current = true; - setCodeError(''); - void (async () => { - try { - setPhase('linking'); - const { rid, cliSk, relay } = stateRef.current!; - const codeHashHex = bytesToHex(computeCodeHash(rid, code)); - const encrypted = await relay.retrieve(rid, codeHashHex); - const payload = decryptSession(encrypted, cliSk, code, rid); - const session = sessionPayloadToWalletSession(payload); - await saveWalletSession(name, session); - await deleteWalletRequest(stateRef.current!.rid); - setAddress(session.walletAddress); - setWalletChain(session.chain); - setPhase('done'); - onComplete?.(session.walletAddress, session.chainId, session.chain); - // Fetch balances after a short delay then exit - setPhase('balances'); - try { - const accessKey = - process.env.SEQUENCE_INDEXER_ACCESS_KEY || - session.projectAccessKey || - process.env.SEQUENCE_PROJECT_ACCESS_KEY; - if (accessKey) { - const network = resolveNetwork(session.chain); - const nativeSymbol = network.nativeToken?.symbol || 'POL'; - const nativeDecimals = network.nativeToken?.decimals ?? 18; - const { SequenceIndexer } = await import('@0xsequence/indexer'); - const chainNames: Record = { - 137: 'polygon', - 80002: 'amoy', - 1: 'mainnet', - 42161: 'arbitrum', - 10: 'optimism', - 8453: 'base' - }; - const chainSlug = chainNames[network.chainId] || 'polygon'; - const indexer = new SequenceIndexer( - `https://${chainSlug}-indexer.sequence.app`, - accessKey - ); - const [nativeRes, tokenRes] = await Promise.all([ - indexer.getNativeTokenBalance({ accountAddress: session.walletAddress }), - indexer.getTokenBalances({ - accountAddress: session.walletAddress, - includeMetadata: true - }) - ]); - const rows: BalanceRow[] = [ - { - symbol: nativeSymbol, - balance: formatUnits(BigInt(nativeRes?.balance?.balance || '0'), nativeDecimals) - } - ]; - for (const b of tokenRes?.balances || []) { - const sym = b.contractInfo?.symbol || 'ERC20'; - const dec = b.contractInfo?.decimals ?? 18; - const bal = formatUnits(b.balance || '0', dec); - if (parseFloat(bal) > 0) rows.push({ symbol: sym, balance: bal }); - } - setBalances(rows); - } - } catch { - // balance fetch failure is non-fatal - } - setPhase('done'); - exit(); - } catch (e: unknown) { - if (e instanceof RelayCodeError && e.attemptsRemaining > 0) { - submittingRef.current = false; - setCode(''); - setCodeError( - `Incorrect code — ${e.attemptsRemaining} attempt${e.attemptsRemaining === 1 ? '' : 's'} remaining` - ); - setPhase('code'); - } else { - const msg = e instanceof Error ? e.message : String(e); - setError(msg); - setPhase('error'); - onError?.(msg); - exit(new Error(msg)); - } - } - })(); - } - }, [phase, code]); - - const regStatus: 'active' | 'done' | 'error' = - phase === 'registering' ? 'active' : phase === 'error' && !url ? 'error' : 'done'; - - const waitStatus: 'pending' | 'active' | 'done' | 'error' = - phase === 'registering' - ? 'pending' - : phase === 'waiting' - ? 'active' - : ['code', 'nocode', 'linking', 'done'].includes(phase) - ? 'done' - : phase === 'error' - ? 'error' - : 'pending'; - - const linkStatus: 'pending' | 'active' | 'done' | 'error' = [ - 'registering', - 'waiting', - 'code', - 'nocode' - ].includes(phase) - ? 'pending' - : phase === 'linking' - ? 'active' - : phase === 'done' - ? 'done' - : phase === 'error' - ? 'error' - : 'pending'; - - return ( - - {/* Only listen for keystrokes when we have a TTY. Mounting useInput() - in a non-TTY context triggers Ink's raw-mode setup, which throws - "Raw mode is not supported on the current process.stdin". */} - {tty && } - -
- - {/* Steps */} - - - - - {/* URL box — shown during waiting/code/nocode/linking */} - {url && ['waiting', 'code', 'nocode', 'linking'].includes(phase) && ( - - )} - - {/* Non-TTY: browser approved but can't enter code interactively */} - {phase === 'nocode' && ( - - - - Browser approved — enter your code: - - - run - {`polygon-agent wallet import --rid ${rid} --code <6-digit-code>`} - - - )} - - {/* Code entry — shown during code phase (TTY only) */} - {phase === 'code' && ( - - - Enter the 6-digit code shown in your browser - - {codeError && {codeError}} - - - )} - - {/* Linking spinner detail */} - {phase === 'linking' && ( - - decrypting session... - - )} - - {/* Balance fetching spinner */} - {phase === 'balances' && ( - - - - - fetching wallet balances... - - )} - - {/* Success */} - {phase === 'done' && ( - - - - Wallet ready - · - {name} - - - - - - {balances.length > 0 && ( - - {'─'.repeat(36)} - {balances.map((b) => ( - - - - {b.symbol} - - - {b.balance} - - ))} - - )} - polygon-agent balances - - )} - - {phase === 'error' && } - - ); -} - -// Ink UI for wallet list export interface WalletInfo { name: string; address: string; @@ -466,7 +17,7 @@ export function WalletListUI({ wallets }: { wallets: WalletInfo[] }) { {wallets.length === 0 ? ( No wallets found. Run: - polygon-agent wallet create + agent wallet login ) : ( diff --git a/packages/polygon-agent-cli/src/commands/wallet.ts b/packages/polygon-agent-cli/src/commands/wallet.ts index ba04401..edee8ec 100644 --- a/packages/polygon-agent-cli/src/commands/wallet.ts +++ b/packages/polygon-agent-cli/src/commands/wallet.ts @@ -1,444 +1,218 @@ -import type { Argv, CommandModule } from 'yargs'; +import type { CommandModule } from 'yargs'; -import fs from 'node:fs'; -import os from 'node:os'; -import path from 'node:path'; +import { randomBytes } from 'node:crypto'; import React from 'react'; +import type { OmsRelayOidcProvider } from '@polygonlabs/oms-wallet'; + +import { OmsRelayOidcProviders } from '@polygonlabs/oms-wallet'; + +import type { OmsLoginMethod } from '../lib/storage.ts'; + +import { runBrowserLogin } from '../lib/browser-login.ts'; +import { ensureBuilderAccessKey, makeDefaultProvisionDeps } from '../lib/builder-provision.ts'; +import { makeLoginRelay } from '../lib/login-relay-client.ts'; +import { startOidcCallbackServer } from '../lib/oidc-callback-server.ts'; +import { getOmsClient, loginUiBaseUrl, oidcRelayBaseUrl } from '../lib/oms-client.ts'; import { - generateX25519Keypair, - bytesToHex, - hexToBytes, - computeCodeHash, - decryptSession -} from '@polygonlabs/agent-shared'; - -import { RelayClient } from '../lib/relay-client.ts'; -import { - saveWalletSession, - loadWalletSession, - saveWalletRequest, - loadWalletRequest, - deleteWalletRequest, listWallets, deleteWallet, - sessionPayloadToWalletSession + saveOmsWalletPointer, + loadOmsWalletPointer, + deleteOmsWallet } from '../lib/storage.ts'; -import { normalizeChain, resolveNetwork, fileCoerce } from '../lib/utils.ts'; import { isTTY, inkRender } from '../ui/render.js'; -import { WalletCreateUI, WalletListUI, WalletAddressUI } from './wallet-ui.js'; +import { showFunding } from './operations.ts'; +import { WalletListUI, WalletAddressUI } from './wallet-ui.js'; // Compact JSON output for AI agent consumers (single line, no stack traces) function jsonOut(data: Record): void { console.log(JSON.stringify(data)); } -// Base64 URL decode -function b64urlDecode(str: string): Buffer { - const norm = str.replace(/-/g, '+').replace(/_/g, '/'); - const pad = norm.length % 4 === 0 ? '' : '='.repeat(4 - (norm.length % 4)); - return Buffer.from(norm + pad, 'base64'); +// --- Subcommand: wallet login (Google OIDC browser flow — the only login) --- +interface LoginArgs { + name: string; + provider: string; + port: number; + timeout: number; + force: boolean; + fund: boolean; + local: boolean; + remote: boolean; + relayUrl?: string; } -// Contracts always whitelisted in sessions. -// Spending limits (nativeLimit, usdcLimit, etc.) are enforced independently — -// whitelisting only permits the contract to be called, it does not grant token spend. -const AUTO_WHITELISTED_CONTRACTS = [ - '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432', // ERC-8004 IdentityRegistry - '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63', // ERC-8004 ReputationRegistry - '0xABAAd93EeE2a569cF0632f39B10A9f5D734777ca', // ValueForwarder (required for send native POL) - // NOTE: Trails deposit contract for swap --from POL is dynamic (changes per route/quote) - // and cannot be reliably pre-whitelisted here. - - // Polygon mainnet (chainId 137) — default tokens - '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', // USDC (native) - '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', // USDC.e (bridged) - - // Polygon mainnet (chainId 137) — yield vaults (always available for deposit) - '0x794a61358d6845594f94dc1db02a252b5b4814ad' // Aave V3 Pool (all markets) -]; - -// Additional contracts whitelisted when --defi flag is passed. -// Covers ERC-20s and yield vaults needed for swaps, bridges, and deposits. -const DEFI_CONTRACTS = [ - // Polygon mainnet (chainId 137) — additional ERC-20 token contracts - '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', // USDT - '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', // WETH - - // Polygon mainnet (chainId 137) — additional yield vaults - '0x781fb7f6d845e3be129289833b04d43aa8558c42', // Morpho Compound USDC - '0xf5c81d25ee174d83f1fd202ca94ae6070d073ccf', // Morpho Compound WETH - '0x3f33f9f7e2d7cfbcbdf8ea8b870a6e3d449664c2' // Morpho Compound POL -]; - -// Session permission options shared by create subcommands -interface SessionPermissionArgs { - 'native-limit'?: string; - 'usdc-limit'?: string; - 'usdt-limit'?: string; - 'token-limit'?: string[]; - contract?: string[]; - defi?: boolean; - 'usdc-to'?: string; - 'usdc-amount'?: string; - 'access-key'?: string; +// Print the auth URL (copy-paste fallback) and try to open it in a browser. +async function announceAuthUrl(url: string): Promise { + process.stderr.write(`\nOpen this URL to sign in:\n${url}\n\n`); + try { + const { default: open } = await import('open'); + await open(url); + } catch { + // open() can fail in headless/remote environments — the URL is already printed. + } + if (isTTY()) { + process.stderr.write('Waiting for browser login… (Ctrl-C to cancel)\n'); + } } -function addSessionPermissionOptions(yargs: Argv): Argv { - return yargs - .option('native-limit', { - type: 'string', - describe: 'POL spending limit' - }) - .option('usdc-limit', { - type: 'string', - describe: 'USDC spending limit' - }) - .option('usdt-limit', { - type: 'string', - describe: 'USDT spending limit' - }) - .option('token-limit', { - type: 'string', - array: true, - describe: 'Token limit, repeatable (e.g. WETH:0.1)' - }) - .option('contract', { - type: 'string', - array: true, - describe: 'Whitelist contract, repeatable' - }) - .option('defi', { - type: 'boolean', - describe: 'Whitelist DeFi contracts (swaps, yield vaults) in addition to defaults' - }) - .option('usdc-to', { - type: 'string', - describe: 'One-off USDC transfer recipient' - }) - .option('usdc-amount', { - type: 'string', - describe: 'One-off USDC transfer amount' - }) - .option('access-key', { - type: 'string', - describe: 'Project access key' +// Legacy --local flow: a short-lived loopback server. The OMS relay now owns +// the Google OAuth callback and bounces the browser back to our nominated +// `omsRelayReturnUri`, which we set to this loopback URL. Only works when the +// browser runs on this machine (and the OMS relay allows a localhost return URI). +async function obtainLoopbackCallbackUrl( + oms: ReturnType, + argv: LoginArgs +): Promise { + const server = await startOidcCallbackServer({ + port: argv.port, + timeoutMs: argv.timeout * 1000 + }); + try { + const { authorizationUrl } = await oms.wallet.startOidcRedirectAuth({ + provider: OmsRelayOidcProviders.google, + omsRelayReturnUri: server.redirectUri }); -} - -function applySessionPermissionParams(url: URL, argv: SessionPermissionArgs): void { - const usdcTo = argv['usdc-to']; - const usdcAmount = argv['usdc-amount']; - if (usdcTo || usdcAmount) { - if (!usdcTo || !usdcAmount) throw new Error('Must provide both --usdc-to and --usdc-amount'); - url.searchParams.set('erc20', 'usdc'); - url.searchParams.set('erc20To', usdcTo); - url.searchParams.set('erc20Amount', usdcAmount); + await announceAuthUrl(authorizationUrl); + return await server.waitForCallbackUrl; + } finally { + server.close(); } - - const nativeLimit = argv['native-limit']; - const usdcLimit = argv['usdc-limit']; - const usdtLimit = argv['usdt-limit']; - if (nativeLimit) url.searchParams.set('nativeLimit', nativeLimit); - if (usdcLimit) url.searchParams.set('usdcLimit', usdcLimit); - if (usdtLimit) url.searchParams.set('usdtLimit', usdtLimit); - - const tokenLimits = (argv['token-limit'] || []) - .map((s) => String(s || '').trim()) - .filter(Boolean); - if (tokenLimits.length) url.searchParams.set('tokenLimits', tokenLimits.join(',')); - - const baseContracts = argv.defi - ? [...AUTO_WHITELISTED_CONTRACTS, ...DEFI_CONTRACTS] - : AUTO_WHITELISTED_CONTRACTS; - const userContracts = (argv.contract || []).map((s) => String(s || '').trim()).filter(Boolean); - const allContracts = [...new Set([...baseContracts, ...userContracts])]; - url.searchParams.set('contracts', allContracts.join(',')); } -// Shared helper: decrypt ciphertext and save wallet session -async function decryptAndSaveSession( - name: string, - ciphertext: string, - rid: string -): Promise<{ walletAddress: string; chainId: number; chain: string }> { - const request = await loadWalletRequest(rid); - if (!request) { - throw new Error(`Request not found: ${rid}`); - } - - const chain = normalizeChain(request.chain || 'polygon'); - - const exp = Date.parse(request.expiresAt); - if (Number.isFinite(exp) && Date.now() > exp) { - throw new Error( - `Request rid=${rid} is expired (expiresAt=${request.expiresAt}). Create a new request.` - ); - } - - const publicKey = b64urlDecode(request.publicKeyB64u); - const privateKey = b64urlDecode(request.privateKeyB64u); - const ciphertextBuf = b64urlDecode(ciphertext); - - // Dynamic import to avoid bundling sealedbox if not needed - const sealedbox = (await import('tweetnacl-sealedbox-js')).default; - const decrypted = sealedbox.open(ciphertextBuf, publicKey, privateKey); - if (!decrypted) { - throw new Error('Failed to decrypt ciphertext'); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let payload: any; +async function handleLogin(argv: LoginArgs): Promise { try { - const { jsonRevivers } = await import('@0xsequence/dapp-client'); - payload = JSON.parse(Buffer.from(decrypted).toString('utf8'), jsonRevivers); - } catch { - payload = JSON.parse(Buffer.from(decrypted).toString('utf8')); - } - - const walletAddress = payload.walletAddress; - const chainId = payload.chainId; - const explicitSession = payload.explicitSession; - const implicit = payload.implicit; - - if (!walletAddress || typeof walletAddress !== 'string') { - throw new Error('Missing walletAddress in payload'); - } - if (!chainId || typeof chainId !== 'number') { - throw new Error('Missing chainId in payload'); - } - - const net = resolveNetwork(chain); - if (Number(net.chainId) !== Number(chainId)) { - throw new Error( - `Chain mismatch: request chain=${chain} (chainId=${net.chainId}) but payload chainId=${chainId}` - ); - } + const oms = getOmsClient(argv.name); + // Zero-setup onboarding: give this agent its own Builder project + access + // key (indexer and Trails quota). Best-effort: a failure never fails the + // login; re-running `wallet login` retries it, no fresh browser auth needed. + async function provisionBuilder(walletAddress: string): Promise { + const provision = await ensureBuilderAccessKey(walletAddress, makeDefaultProvisionDeps()); + const ok = provision.provisioned || provision.reason === 'existing'; + if (!ok) { + process.stderr.write( + `Note: Builder provisioning failed (${provision.reason}). ` + + 'Indexer and Trails calls fall back to shared defaults; re-run `wallet login` to retry.\n' + ); + } + return ok; + } - if (!explicitSession || typeof explicitSession !== 'object') { - throw new Error('Missing explicitSession in payload'); - } - if (!explicitSession.pk || typeof explicitSession.pk !== 'string') { - throw new Error('Missing explicitSession.pk in payload'); - } - if (!implicit?.pk || !implicit?.attestation || !implicit?.identitySignature) { - throw new Error('Missing implicit session in payload'); - } + // Short-circuit if already logged in (the SDK restores the session from + // storage on construction). Starting a new auth would clearSession(), so + // re-login is opt-in via --force. Builder provisioning still runs here: + // a transient failure during the original login must be repairable by + // re-running `wallet login` without forcing a fresh browser auth. + if (!argv.force && oms.wallet.walletAddress) { + const builderProvisioned = await provisionBuilder(oms.wallet.walletAddress); + jsonOut({ + ok: true, + walletName: argv.name, + walletAddress: oms.wallet.walletAddress, + alreadyLoggedIn: true, + builderProvisioned + }); + return; + } - const implicitMeta = { - guard: implicit.guard, - loginMethod: implicit.loginMethod, - userEmail: implicit.userEmail - }; - - const { jsonReplacers } = await import('@0xsequence/dapp-client'); - await saveWalletSession(name, { - walletAddress, - chainId, - chain, - projectAccessKey: request.projectAccessKey || null, - explicitSession: JSON.stringify(explicitSession, jsonReplacers), - sessionPk: explicitSession.pk, - implicitPk: implicit.pk, - implicitMeta: JSON.stringify(implicitMeta, jsonReplacers), - implicitAttestation: JSON.stringify(implicit.attestation, jsonReplacers), - implicitIdentitySig: JSON.stringify(implicit.identitySignature, jsonReplacers), - createdAt: new Date().toISOString() - }); + let walletAddress: string; + let loginMethod: OmsLoginMethod; - return { walletAddress, chainId, chain }; -} + if (argv.local) { + if (argv.provider !== 'google') { + throw new Error( + `Unsupported provider "${argv.provider}". Only "google" works with --local.` + ); + } + const callbackUrl = await obtainLoopbackCallbackUrl(oms, argv); + const result = await oms.wallet.completeOidcRedirectAuth({ + callbackUrl, + walletSelection: 'automatic' + }); + if (!result) { + throw new Error('OIDC login did not complete: no wallet result returned.'); + } + walletAddress = result.walletAddress; + loginMethod = 'google'; + } else { + if (argv.remote) { + process.stderr.write('--remote is deprecated: the default login already works remotely.\n'); + } + const relayBase = argv.relayUrl?.replace(/\/+$/, '') || oidcRelayBaseUrl(); + const result = await runBrowserLogin( + { + relay: makeLoginRelay(relayBase), + wallet: { + startOidcRedirectAuth: (p) => + oms.wallet.startOidcRedirectAuth({ + provider: p.provider as OmsRelayOidcProvider, + omsRelayReturnUri: p.omsRelayReturnUri + }), + completeOidcRedirectAuth: async (p) => { + const r = await oms.wallet.completeOidcRedirectAuth(p); + if (!r) { + throw new Error('OIDC login did not complete: no wallet result returned.'); + } + return { walletAddress: r.walletAddress }; + }, + startEmailAuth: (p) => oms.wallet.startEmailAuth(p), + completeEmailAuth: (p) => oms.wallet.completeEmailAuth(p) + }, + oidcProviderGoogle: OmsRelayOidcProviders.google, + announce: announceAuthUrl, + sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)), + now: () => Date.now(), + randomSessionId: () => randomBytes(16).toString('base64url') + }, + { + relayBase, + uiBase: loginUiBaseUrl(), + timeoutMs: argv.timeout * 1000 + } + ); + walletAddress = result.walletAddress; + loginMethod = result.loginMethod; + } -// --- Subcommand: wallet create --- -interface CreateArgs extends SessionPermissionArgs { - name: string; - chain: string; - 'print-url': boolean; - timeout: number; -} + await saveOmsWalletPointer(argv.name, { + walletAddress, + loginMethod, + createdAt: new Date().toISOString() + }); -async function handleCreate(argv: CreateArgs): Promise { - if (argv['print-url']) { - await handleCreateNoWait(argv); - } else { - await handleCreateAndWait(argv); - } -} + const builderProvisioned = await provisionBuilder(walletAddress); -async function handleCreateNoWait(argv: CreateArgs): Promise { - const name = argv.name; - const chainArg = argv.chain; + jsonOut({ ok: true, walletName: argv.name, walletAddress, loginMethod, builderProvisioned }); - try { - const chain = normalizeChain(chainArg); - const connectorBase = ( - process.env.SEQUENCE_ECOSYSTEM_CONNECTOR_URL || 'https://agentconnect.polygon.technology' - ).replace(/\/$/, ''); - - const { secretKey: cliSk, publicKey: cliPk } = generateX25519Keypair(); - const cliPkHex = bytesToHex(cliPk); - const cliSkHex = bytesToHex(cliSk); - - const relay = new RelayClient(connectorBase); - const rid = await relay.createRequest(cliPkHex); - - const projectAccessKey = argv['access-key'] || process.env.SEQUENCE_PROJECT_ACCESS_KEY; - const expiresAt = new Date(Date.now() + 10 * 60 * 1000).toISOString(); - - await saveWalletRequest(rid, { - rid, - walletName: name, - chain, - createdAt: new Date().toISOString(), - expiresAt, - publicKeyB64u: '', - privateKeyB64u: '', - projectAccessKey: projectAccessKey || null, - cliSkHex - }); - - const url = new URL(`${connectorBase}/link`); - url.searchParams.set('rid', rid); - url.searchParams.set('wallet', name); - url.searchParams.set('chain', chain); - if (projectAccessKey) url.searchParams.set('accessKey', projectAccessKey); - applySessionPermissionParams(url, argv); - - const fullUrl = url.toString(); - jsonOut({ - ok: true, - rid, - approvalUrl: fullUrl, - next: `polygon-agent wallet import --rid ${rid} --code <6-digit-code>` - }); + // Funding: the login page's success screen already directs the user onward, + // so the browser flow only prints the panel; --local keeps opening the page. + if (argv.fund !== false) { + await showFunding(argv.name, walletAddress, 137, { openBrowser: argv.local }); + } } catch (error) { jsonOut({ ok: false, error: (error as Error).message }); process.exit(1); } } -async function handleCreateAndWait(argv: CreateArgs): Promise { - const name = argv.name; - const chain = argv.chain; - const tty = isTTY(); - let failed = false; - try { - // Always use Ink — renders to stdout (TTY) or stderr (non-TTY, keeps stdout clean for JSON) - await inkRender( - React.createElement(WalletCreateUI, { - name, - chain, - timeout: argv.timeout, - argv, - tty, - onComplete: (walletAddress: string, chainId: number, chainName: string) => { - if (!tty) { - jsonOut({ ok: true, walletAddress, chainId, chain: chainName }); - } - }, - onError: (message: string) => { - if (!tty) jsonOut({ ok: false, error: message }); - } - }), - { useStderr: !tty } - ); - } catch { - failed = true; - } - if (failed) process.exit(1); -} - -// --- Subcommand: wallet import (alias: start-session) --- -interface ImportArgs { +// --- Subcommand: wallet logout --- +interface LogoutArgs { name: string; - ciphertext?: string; - rid?: string; - code?: string; } -async function handleImport(argv: ImportArgs): Promise { +async function handleLogout(argv: LogoutArgs): Promise { const name = argv.name; - try { - // Relay-based code import - if (argv.code) { - const code = argv.code.trim(); - let rid = argv.rid; - - if (!rid) { - // Find the most recent v2 request for this wallet - const requestFiles = fs - .readdirSync(path.join(os.homedir(), '.polygon-agent', 'requests')) - .filter((f) => f.endsWith('.json')) - .sort() - .reverse(); - - for (const file of requestFiles) { - const requestRid = file.replace('.json', ''); - const request = await loadWalletRequest(requestRid); - if (request && request.walletName === name && request.cliSkHex) { - rid = requestRid; - break; - } - } - if (!rid) - throw new Error( - `No pending relay request for wallet '${name}'. Run: polygon-agent wallet create --print-url` - ); - } - - const request = await loadWalletRequest(rid!); - if (!request?.cliSkHex) throw new Error(`Request ${rid} is not a relay-based request`); - - const connectorBase = ( - process.env.SEQUENCE_ECOSYSTEM_CONNECTOR_URL || 'https://agentconnect.polygon.technology' - ).replace(/\/$/, ''); - - const relay = new RelayClient(connectorBase); - const cliSk = hexToBytes(request.cliSkHex); - const codeHashHex = bytesToHex(computeCodeHash(rid!, code)); - const encrypted = await relay.retrieve(rid!, codeHashHex); - const payload = decryptSession(encrypted, cliSk, code, rid!); - - const session = sessionPayloadToWalletSession(payload); - await saveWalletSession(name, session); - await deleteWalletRequest(rid!); - - jsonOut({ - ok: true, - walletAddress: session.walletAddress, - chain: session.chain, - chainId: session.chainId - }); - return; - } - - // Legacy ciphertext-based import (backward compat) - if (!argv.ciphertext) { - throw new Error('Provide either --code (relay mode) or --ciphertext (legacy mode)'); - } - const ciphertext = fileCoerce(argv.ciphertext); - let rid = argv.rid; - - if (!rid) { - const requestFiles = fs - .readdirSync(path.join(os.homedir(), '.polygon-agent', 'requests')) - .filter((f) => f.endsWith('.json')); - - for (const file of requestFiles) { - const requestRid = file.replace('.json', ''); - const request = await loadWalletRequest(requestRid); - if (request && request.walletName === name) { - rid = requestRid; - break; - } - } - if (!rid) throw new Error(`No matching request found for wallet '${name}'`); + try { + const oms = getOmsClient(name); + await oms.wallet.signOut(); + } catch { + // signOut may fail if no session/config — proceed to delete local state anyway } - - const { walletAddress, chainId, chain } = await decryptAndSaveSession(name, ciphertext, rid); - jsonOut({ ok: true, walletAddress, chainId, chain }); + await deleteOmsWallet(name); + jsonOut({ ok: true, walletName: name, loggedOut: true }); } catch (error) { jsonOut({ ok: false, error: (error as Error).message }); process.exit(1); @@ -450,15 +224,22 @@ async function handleList(): Promise { try { const wallets = await listWallets(); - const details: Array<{ name: string; address: string; chain: string; chainId: number }> = []; + const details: Array<{ + name: string; + address: string; + chain: string; + chainId: number; + loginMethod?: string; + }> = []; for (const name of wallets) { - const session = await loadWalletSession(name); - if (session) { + const pointer = await loadOmsWalletPointer(name); + if (pointer) { details.push({ name, - address: session.walletAddress, - chain: session.chain, - chainId: session.chainId + address: pointer.walletAddress, + chain: 'polygon', + chainId: 137, + loginMethod: pointer.loginMethod }); } } @@ -483,25 +264,26 @@ async function handleAddress(argv: AddressArgs): Promise { const name = argv.name; try { - const session = await loadWalletSession(name); - if (!session) { - throw new Error(`Wallet not found: ${name}`); + const pointer = await loadOmsWalletPointer(name); + if (!pointer) { + throw new Error(`Wallet not found: ${name}. Run: agent wallet login`); } if (!isTTY()) { jsonOut({ ok: true, - walletAddress: session.walletAddress, - chain: session.chain, - chainId: session.chainId + walletAddress: pointer.walletAddress, + chain: 'polygon', + chainId: 137, + loginMethod: pointer.loginMethod }); } else { await inkRender( React.createElement(WalletAddressUI, { name, - address: session.walletAddress, - chain: session.chain, - chainId: session.chainId + address: pointer.walletAddress, + chain: 'polygon', + chainId: 137 }) ); } @@ -520,6 +302,9 @@ async function handleRemove(argv: RemoveArgs): Promise { const name = argv.name; try { + // Remove OMS session state (storage + credential key) if present, plus the + // wallet pointer file. + await deleteOmsWallet(name); const deleted = await deleteWallet(name); if (!deleted) { @@ -536,41 +321,12 @@ async function handleRemove(argv: RemoveArgs): Promise { // --- Main wallet command --- export const walletCommand: CommandModule = { command: 'wallet', - describe: 'Manage wallets (create, import, list, address, remove)', + describe: 'Manage wallets (login, logout, list, address, remove)', builder: (yargs) => yargs .command({ - command: 'create', - describe: 'Create wallet (auto-waits for approval)', - builder: (y) => - addSessionPermissionOptions( - y - .option('name', { - type: 'string', - default: 'main', - describe: 'Wallet name' - }) - .option('chain', { - type: 'string', - default: 'polygon', - describe: 'Chain name or ID' - }) - .option('print-url', { - type: 'boolean', - default: false, - describe: 'Print approval URL and exit (non-interactive)' - }) - .option('timeout', { - type: 'number', - default: 300, - describe: 'Seconds to wait for approval before timing out' - }) - ), - handler: (argv) => handleCreate(argv as unknown as CreateArgs) - }) - .command({ - command: 'import', - describe: 'Import session from relay code or legacy ciphertext', + command: 'login', + describe: 'Log in from the browser (choose Google or email on the login page)', builder: (y) => y .option('name', { @@ -578,43 +334,58 @@ export const walletCommand: CommandModule = { default: 'main', describe: 'Wallet name' }) - .option('code', { + .option('provider', { type: 'string', - describe: '6-digit code from browser (for relay-based sessions)' + default: 'google', + describe: 'OIDC provider for --local (the browser flow picks the method on the page)' }) - .option('ciphertext', { - type: 'string', - describe: 'Encrypted blob (legacy mode, or use @file)' + .option('port', { + type: 'number', + default: 8765, + describe: 'Localhost callback port for the --local loopback flow; default 8765' }) - .option('rid', { - type: 'string', - describe: 'Request ID (auto-detected if omitted)' - }), - handler: (argv) => handleImport(argv as unknown as ImportArgs) - }) - .command({ - command: 'start-session', - describe: false, - builder: (y) => - y - .option('name', { - type: 'string', - default: 'main', - describe: 'Wallet name' + .option('timeout', { + type: 'number', + default: 600, + describe: 'Seconds to wait for the browser login before giving up' }) - .option('code', { - type: 'string', - describe: '6-digit code from browser (for relay-based sessions)' + .option('force', { + type: 'boolean', + default: false, + describe: 'Re-login even if a session already exists' }) - .option('ciphertext', { - type: 'string', - describe: 'Encrypted session blob' + .option('fund', { + type: 'boolean', + default: true, + describe: 'Show the funding step after login (use --no-fund to skip)' }) - .option('rid', { + .option('remote', { + type: 'boolean', + default: false, + describe: '(deprecated) the default flow already works remotely' + }) + .option('local', { + type: 'boolean', + default: false, + describe: + 'Legacy loopback flow: raw Google URL + localhost callback (browser must be on this machine)' + }) + .option('relay-url', { type: 'string', - describe: 'Request ID' + describe: 'Relay base URL (overrides POLYGON_AGENT_OIDC_RELAY)' }), - handler: (argv) => handleImport(argv as unknown as ImportArgs) + handler: (argv) => handleLogin(argv as unknown as LoginArgs) + }) + .command({ + command: 'logout', + describe: 'Log out and clear the local OMS V3 session', + builder: (y) => + y.option('name', { + type: 'string', + default: 'main', + describe: 'Wallet name' + }), + handler: (argv) => handleLogout(argv as unknown as LogoutArgs) }) .command({ command: 'list', diff --git a/packages/polygon-agent-cli/src/index.ts b/packages/polygon-agent-cli/src/index.ts index 2ad0c7e..4c3fa52 100644 --- a/packages/polygon-agent-cli/src/index.ts +++ b/packages/polygon-agent-cli/src/index.ts @@ -23,13 +23,13 @@ import { import { polymarketCommand } from './commands/polymarket.ts'; import { setupCommand } from './commands/setup.ts'; import { walletCommand } from './commands/wallet.ts'; -import { bootstrapAccessKey } from './lib/storage.ts'; +import { bootstrapOmsConfig } from './lib/storage.ts'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf8')); -// Auto-load access key from ~/.polygon-agent/builder.json if not already in env -bootstrapAccessKey(); +// Auto-load OMS V3 credentials from builder.json if not already in env +bootstrapOmsConfig(); // Legacy aliases — hidden commands that map to the new structure const legacyAliases = [ @@ -83,8 +83,12 @@ const legacyAliases = [ } ]; +// The CLI ships two bin names ("agent" is the primary, "polygon-agent" the +// long-form alias); help and usage text follow whichever one was invoked. +const invokedAs = path.basename(process.argv[1] ?? ''); + const parser = yargs(hideBin(process.argv)) - .scriptName('polygon-agent') + .scriptName(invokedAs === 'agent' ? 'agent' : 'polygon-agent') .version(pkg.version) .command(setupCommand) .command(walletCommand) diff --git a/packages/polygon-agent-cli/src/lib/browser-login.test.ts b/packages/polygon-agent-cli/src/lib/browser-login.test.ts new file mode 100644 index 0000000..b0d5c49 --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/browser-login.test.ts @@ -0,0 +1,169 @@ +import { describe, expect, it } from 'vitest'; + +import type { + BrowserLoginDeps, + BrowserLoginOpts, + LoginAction, + LoginStatus +} from './browser-login.ts'; + +import { runBrowserLogin } from './browser-login.ts'; + +// A sentinel standing in for the SDK's opaque OmsRelayOidcProviders.google value. +const GOOGLE_PROVIDER = Symbol('oms-relay-oidc-provider-google'); + +// A scripted fake: nextAction() pops the queue (null = pending tick), and every +// published status is recorded for assertions. +function makeFakes(actionQueue: Array) { + const statuses: LoginStatus[] = []; + const calls: string[] = []; + let time = 0; + + const deps: BrowserLoginDeps = { + relay: { + registerSession: async () => { + calls.push('registerSession'); + }, + nextAction: async () => (actionQueue.length > 0 ? (actionQueue.shift() ?? null) : null), + setStatus: async (_s, status) => { + statuses.push(status); + } + }, + wallet: { + startOidcRedirectAuth: async (p) => { + calls.push(`startOidc:${String(p.provider === GOOGLE_PROVIDER)}:${p.omsRelayReturnUri}`); + return { authorizationUrl: 'https://accounts.google.com/auth' }; + }, + completeOidcRedirectAuth: async (p) => { + calls.push(`completeOidc:${p.callbackUrl}`); + return { walletAddress: '0xW' }; + }, + startEmailAuth: async (p) => { + calls.push(`startEmail:${p.email}`); + }, + completeEmailAuth: async (p) => { + calls.push(`completeEmail:${p.code}`); + if (p.code === 'BAD') throw new Error('invalid code'); + return { walletAddress: '0xW' }; + } + }, + oidcProviderGoogle: GOOGLE_PROVIDER, + announce: async (url) => { + calls.push(`announce:${url}`); + }, + sleep: async () => { + time += 1000; + }, + now: () => time, + randomSessionId: () => 'sessionid12345678' + }; + return { deps, statuses, calls }; +} + +const OPTS: BrowserLoginOpts = { + relayBase: 'https://relay.test', + uiBase: 'https://ui.test', + timeoutMs: 60_000 +}; + +describe('runBrowserLogin', () => { + it('completes the google flow', async () => { + const { deps, statuses, calls } = makeFakes([ + { type: 'google' }, + { type: 'oidc-callback', callbackUrl: 'https://ui.test/login?s=sessionid12345678' } + ]); + const result = await runBrowserLogin(deps, OPTS); + + expect(result).toEqual({ walletAddress: '0xW', loginMethod: 'google' }); + expect(calls).toContain('announce:https://ui.test/login#sessionid12345678'); + expect(calls).toContain('startOidc:true:https://ui.test/login'); + expect(calls).toContain('completeOidc:https://ui.test/login?s=sessionid12345678'); + expect(statuses).toEqual([ + { status: 'auth-url', url: 'https://accounts.google.com/auth' }, + { status: 'done', walletAddress: '0xW' } + ]); + }); + + it('completes the email flow', async () => { + const { deps, statuses, calls } = makeFakes([ + { type: 'email', email: 'a@b.co' }, + { type: 'otp', code: '123456' } + ]); + const result = await runBrowserLogin(deps, OPTS); + + expect(result).toEqual({ walletAddress: '0xW', loginMethod: 'email' }); + expect(calls).toContain('startEmail:a@b.co'); + expect(calls).toContain('completeEmail:123456'); + expect(statuses).toEqual([{ status: 'otp-sent' }, { status: 'done', walletAddress: '0xW' }]); + }); + + it('publishes otp-invalid and accepts a retried code', async () => { + const { deps, statuses } = makeFakes([ + { type: 'email', email: 'a@b.co' }, + { type: 'otp', code: 'BAD' }, + { type: 'otp', code: '123456' } + ]); + const result = await runBrowserLogin(deps, OPTS); + + expect(result.loginMethod).toBe('email'); + expect(statuses).toEqual([ + { status: 'otp-sent' }, + { status: 'otp-invalid', attemptsLeft: 2 }, + { status: 'done', walletAddress: '0xW' } + ]); + }); + + it('fails after three bad codes', async () => { + const { deps, statuses } = makeFakes([ + { type: 'email', email: 'a@b.co' }, + { type: 'otp', code: 'BAD' }, + { type: 'otp', code: 'BAD' }, + { type: 'otp', code: 'BAD' } + ]); + await expect(runBrowserLogin(deps, OPTS)).rejects.toThrow(/too many invalid codes/i); + expect(statuses.at(-1)).toMatchObject({ status: 'error' }); + }); + + it('throws when the user cancels on the page', async () => { + const { deps, statuses } = makeFakes([{ type: 'cancel' }]); + await expect(runBrowserLogin(deps, OPTS)).rejects.toThrow(/cancelled/i); + expect(statuses.at(-1)).toMatchObject({ status: 'error' }); + }); + + it('cancels while waiting for the oidc callback', async () => { + const { deps, statuses } = makeFakes([{ type: 'google' }, { type: 'cancel' }]); + await expect(runBrowserLogin(deps, OPTS)).rejects.toThrow(/cancelled/i); + expect(statuses.at(-1)).toMatchObject({ status: 'error' }); + }); + + it('times out when no action ever arrives', async () => { + const { deps } = makeFakes([]); + await expect(runBrowserLogin(deps, { ...OPTS, timeoutMs: 5000 })).rejects.toThrow(/timed out/i); + }); + + it('propagates a relay registration failure', async () => { + const { deps } = makeFakes([]); + deps.relay.registerSession = async () => { + throw new Error('Relay register failed (503)'); + }; + await expect(runBrowserLogin(deps, OPTS)).rejects.toThrow(/Relay register failed/); + }); + + it('publishes an error status when the provider auth start fails', async () => { + const { deps, statuses } = makeFakes([{ type: 'google' }]); + deps.wallet.startOidcRedirectAuth = async () => { + throw new Error('provider down'); + }; + await expect(runBrowserLogin(deps, OPTS)).rejects.toThrow(/provider down/); + expect(statuses.at(-1)).toEqual({ status: 'error', message: 'provider down' }); + }); + + it('publishes an error status when the relay action poll fails', async () => { + const { deps, statuses } = makeFakes([]); + deps.relay.nextAction = async () => { + throw new Error('Relay poll failed (500)'); + }; + await expect(runBrowserLogin(deps, OPTS)).rejects.toThrow(/Relay poll failed/); + expect(statuses.at(-1)).toEqual({ status: 'error', message: 'Relay poll failed (500)' }); + }); +}); diff --git a/packages/polygon-agent-cli/src/lib/browser-login.ts b/packages/polygon-agent-cli/src/lib/browser-login.ts new file mode 100644 index 0000000..2e1bc6e --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/browser-login.ts @@ -0,0 +1,157 @@ +// The browser-login action loop: the branded page (agentconnect-ui /login) is +// the input surface, the relay carries user actions here, and this process +// drives the actual SDK auth so keys and the PKCE verifier never leave the +// machine. Pure orchestration over injected deps so it is unit-testable. + +export type LoginAction = + | { type: 'google' } + | { type: 'oidc-callback'; callbackUrl: string } + | { type: 'email'; email: string } + | { type: 'otp'; code: string } + | { type: 'cancel' }; + +export type LoginStatus = + | { status: 'awaiting-method' } + | { status: 'auth-url'; url: string } + | { status: 'otp-sent' } + | { status: 'otp-invalid'; attemptsLeft?: number } + | { status: 'done'; walletAddress: string } + | { status: 'error'; message: string }; + +export interface BrowserLoginDeps { + relay: { + registerSession(session: string): Promise; + nextAction(session: string): Promise; + setStatus(session: string, status: LoginStatus): Promise; + }; + wallet: { + startOidcRedirectAuth(p: { + provider: unknown; + omsRelayReturnUri: string; + }): Promise<{ authorizationUrl: string }>; + completeOidcRedirectAuth(p: { + callbackUrl: string; + walletSelection: 'automatic'; + }): Promise<{ walletAddress: string }>; + startEmailAuth(p: { email: string }): Promise; + completeEmailAuth(p: { + code: string; + walletSelection: 'automatic'; + }): Promise<{ walletAddress: string }>; + }; + // The SDK's opaque Google provider value (OmsRelayOidcProviders.google), injected + // so this file stays SDK-agnostic and unit tests can fake it with a sentinel. + oidcProviderGoogle: unknown; + announce(url: string): Promise; + sleep(ms: number): Promise; + now(): number; + randomSessionId(): string; +} + +export interface BrowserLoginOpts { + relayBase: string; + uiBase: string; + timeoutMs: number; + pollIntervalMs?: number; +} + +const MAX_OTP_ATTEMPTS = 3; + +export async function runBrowserLogin( + deps: BrowserLoginDeps, + opts: BrowserLoginOpts +): Promise<{ walletAddress: string; loginMethod: 'google' | 'email' }> { + const { relay, wallet } = deps; + const interval = opts.pollIntervalMs ?? 2000; + const session = deps.randomSessionId(); + const pageUrl = `${opts.uiBase}/login#${session}`; + const deadline = deps.now() + opts.timeoutMs; + + await relay.registerSession(session); + await deps.announce(pageUrl); + + const runActionLoop = async (): Promise<{ + walletAddress: string; + loginMethod: 'google' | 'email'; + }> => { + let otpFailures = 0; + + while (deps.now() < deadline) { + const action = await relay.nextAction(session); + if (!action) { + await deps.sleep(interval); + continue; + } + + if (action.type === 'cancel') { + throw new Error('Login cancelled in the browser.'); + } + + if (action.type === 'google') { + // The OMS relay validates this return URI against the project's + // allowlist with an exact string match, so it must stay the bare, + // static `/login` (no query): a per-login `?s=` would never match a + // static registration. The pairing session instead survives the + // OAuth round trip via sessionStorage on the page itself, which the + // relay bounces back to with its own callback params appended; the + // page then posts the full return URL back to us as an + // `oidc-callback` action below. + const { authorizationUrl } = await wallet.startOidcRedirectAuth({ + provider: deps.oidcProviderGoogle, + omsRelayReturnUri: `${opts.uiBase}/login` + }); + await relay.setStatus(session, { status: 'auth-url', url: authorizationUrl }); + continue; + } + + if (action.type === 'oidc-callback') { + const result = await wallet.completeOidcRedirectAuth({ + callbackUrl: action.callbackUrl, + walletSelection: 'automatic' + }); + await relay.setStatus(session, { status: 'done', walletAddress: result.walletAddress }); + return { walletAddress: result.walletAddress, loginMethod: 'google' }; + } + + if (action.type === 'email') { + await wallet.startEmailAuth({ email: action.email }); + otpFailures = 0; + await relay.setStatus(session, { status: 'otp-sent' }); + continue; + } + + // action.type === 'otp' + try { + const result = await wallet.completeEmailAuth({ + code: action.code, + walletSelection: 'automatic' + }); + await relay.setStatus(session, { status: 'done', walletAddress: result.walletAddress }); + return { walletAddress: result.walletAddress, loginMethod: 'email' }; + } catch { + otpFailures += 1; + if (otpFailures >= MAX_OTP_ATTEMPTS) { + throw new Error('Login failed: too many invalid codes.'); + } + await relay.setStatus(session, { + status: 'otp-invalid', + attemptsLeft: MAX_OTP_ATTEMPTS - otpFailures + }); + } + } + + throw new Error('Timed out waiting for browser login. Re-run, or use `wallet login --local`.'); + }; + + try { + return await runActionLoop(); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + try { + await relay.setStatus(session, { status: 'error', message }); + } catch { + // Best-effort: the thrown error below is the source of truth. + } + throw error instanceof Error ? error : new Error(message); + } +} diff --git a/packages/polygon-agent-cli/src/lib/builder-api.ts b/packages/polygon-agent-cli/src/lib/builder-api.ts new file mode 100644 index 0000000..f92c41d --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/builder-api.ts @@ -0,0 +1,86 @@ +// Sequence Builder API helpers (GetAuthToken / CreateProject / GetDefaultAccessKey). +// Used by `setup` and by the post-login auto-provisioning in lib/builder-provision.ts. + +export async function getAuthToken(proofString: string): Promise { + const apiUrl = process.env.SEQUENCE_BUILDER_API_URL || 'https://api.sequence.build'; + const url = `${apiUrl}/rpc/Builder/GetAuthToken`; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ ethauthProof: proofString }) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`GetAuthToken failed: ${response.status} ${errorText}`); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const data: any = await response.json(); + + if (!data.ok || !data.auth?.jwtToken) { + throw new Error('GetAuthToken returned invalid response'); + } + + return data.auth.jwtToken; +} + +export async function createProject( + name: string, + jwtToken: string +): Promise<{ id: number; name: string }> { + const apiUrl = process.env.SEQUENCE_BUILDER_API_URL || 'https://api.sequence.build'; + const url = `${apiUrl}/rpc/Builder/CreateProject`; + + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${jwtToken}` + }, + body: JSON.stringify({ name }) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`CreateProject failed: ${response.status} ${errorText}`); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const data: any = await response.json(); + + if (!data.project) { + throw new Error('CreateProject returned invalid response'); + } + + return data.project; +} + +export async function getDefaultAccessKey(projectId: number, jwtToken: string): Promise { + const apiUrl = process.env.SEQUENCE_BUILDER_API_URL || 'https://api.sequence.build'; + const url = `${apiUrl}/rpc/QuotaControl/GetDefaultAccessKey`; + + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${jwtToken}` + }, + body: JSON.stringify({ projectID: projectId }) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`GetDefaultAccessKey failed: ${response.status} ${errorText}`); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const data: any = await response.json(); + + if (!data.accessKey?.accessKey) { + throw new Error('GetDefaultAccessKey returned invalid response'); + } + + return data.accessKey.accessKey; +} diff --git a/packages/polygon-agent-cli/src/lib/builder-provision.test.ts b/packages/polygon-agent-cli/src/lib/builder-provision.test.ts new file mode 100644 index 0000000..f109f0c --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/builder-provision.test.ts @@ -0,0 +1,125 @@ +import { describe, expect, it } from 'vitest'; + +import type { ProvisionDeps } from './builder-provision.ts'; + +import { ensureBuilderAccessKey } from './builder-provision.ts'; + +function makeFakes(overrides: Partial = {}) { + const saved: unknown[] = []; + const deps: ProvisionDeps = { + loadBuilderConfig: async () => null, + saveBuilderConfig: async (cfg) => { + saved.push(cfg); + }, + createEoa: () => ({ + privateKey: '0xkey', + address: '0xE0A0000000000000000000000000000000000001' + }), + generateProof: async () => 'eth.proof', + getAuthToken: async () => 'jwt-1', + createProject: async (name) => ({ id: 4242, name }), + getDefaultAccessKey: async () => 'AQAAAA-access-key', + ...overrides + }; + return { deps, saved }; +} + +const WALLET = '0xc2F4cAfe89AE7e1bcB86dd3f141C0a3adCEB6C17'; + +describe('ensureBuilderAccessKey', () => { + it('provisions a project and saves the credentials', async () => { + const { deps, saved } = makeFakes(); + const result = await ensureBuilderAccessKey(WALLET, deps); + expect(result).toEqual({ provisioned: true }); + expect(saved).toEqual([ + { + privateKey: '0xkey', + eoaAddress: '0xE0A0000000000000000000000000000000000001', + accessKey: 'AQAAAA-access-key', + projectId: 4242 + } + ]); + }); + + it('derives the project name from the wallet address', async () => { + let projectName = ''; + const { deps } = makeFakes({ + createProject: async (name) => { + projectName = name; + return { id: 1, name }; + } + }); + await ensureBuilderAccessKey(WALLET, deps); + expect(projectName).toBe('polygon-agent-c2f4cafe'); + }); + + it('short-circuits when an access key already exists', async () => { + const { deps, saved } = makeFakes({ + loadBuilderConfig: async () => + ({ accessKey: 'existing', projectId: 1, privateKey: 'x', eoaAddress: '0x1' }) as never + }); + const result = await ensureBuilderAccessKey(WALLET, deps); + expect(result).toEqual({ provisioned: false, reason: 'existing' }); + expect(saved).toEqual([]); + }); + + it('reports the failing stage without throwing', async () => { + const { deps: authFail } = makeFakes({ + getAuthToken: async () => { + throw new Error('GetAuthToken failed: 500'); + } + }); + await expect(ensureBuilderAccessKey(WALLET, authFail)).resolves.toEqual({ + provisioned: false, + reason: 'auth: GetAuthToken failed: 500' + }); + + const { deps: projectFail, saved } = makeFakes({ + createProject: async () => { + throw new Error('CreateProject failed: 403'); + } + }); + await expect(ensureBuilderAccessKey(WALLET, projectFail)).resolves.toEqual({ + provisioned: false, + reason: 'project: CreateProject failed: 403' + }); + expect(saved).toEqual([]); + }); + + it('catches a throwing createEoa without rejecting', async () => { + const { deps } = makeFakes({ + createEoa: () => { + throw new Error('entropy unavailable'); + } + }); + await expect(ensureBuilderAccessKey(WALLET, deps)).resolves.toEqual({ + provisioned: false, + reason: 'eoa: entropy unavailable' + }); + }); + + it('reports the access-key stage failure without throwing, and saves nothing', async () => { + const { deps, saved } = makeFakes({ + getDefaultAccessKey: async () => { + throw new Error('GetDefaultAccessKey failed: 500'); + } + }); + await expect(ensureBuilderAccessKey(WALLET, deps)).resolves.toEqual({ + provisioned: false, + reason: 'access-key: GetDefaultAccessKey failed: 500' + }); + expect(saved).toEqual([]); + }); + + it('normalizes a non-Error throw to its string form', async () => { + const { deps } = makeFakes({ + getAuthToken: async () => { + throw 'boom'; + } + }); + await expect(ensureBuilderAccessKey(WALLET, deps)).resolves.toEqual({ + provisioned: false, + reason: 'auth: boom' + }); + }); +}); diff --git a/packages/polygon-agent-cli/src/lib/builder-provision.ts b/packages/polygon-agent-cli/src/lib/builder-provision.ts new file mode 100644 index 0000000..d155bcd --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/builder-provision.ts @@ -0,0 +1,100 @@ +// Post-login Builder provisioning: gives every agent its own Sequence Builder +// project + access key (indexer and Trails quota) with zero manual steps. +// Signs an ETHAuth proof with an ephemeral EOA, exactly like `setup` always +// did, but runs automatically after `wallet login`. Best-effort by contract: +// this function never throws; a failure must never fail a completed login. + +import { ethers } from 'ethers'; + +import { getAuthToken, createProject, getDefaultAccessKey } from './builder-api.ts'; +import { generateEthAuthProof } from './ethauth.ts'; +import { loadBuilderConfigRaw, saveBuilderConfig } from './storage.ts'; + +/** Normalize any thrown value to a message string, even for non-Error throws. */ +const msg = (e: unknown): string => (e instanceof Error ? e.message : String(e)); + +export interface ProvisionDeps { + loadBuilderConfig(): Promise<{ accessKey?: string } | null>; + saveBuilderConfig(cfg: { + privateKey: string; + eoaAddress: string; + accessKey: string; + projectId: number; + }): Promise; + createEoa(): { privateKey: string; address: string }; + generateProof(privateKey: string): Promise; + getAuthToken(proof: string): Promise; + createProject(name: string, jwt: string): Promise<{ id: number; name: string }>; + getDefaultAccessKey(projectId: number, jwt: string): Promise; +} + +export interface ProvisionResult { + provisioned: boolean; + reason?: string; +} + +export function makeDefaultProvisionDeps(): ProvisionDeps { + return { + loadBuilderConfig: async () => loadBuilderConfigRaw(), + saveBuilderConfig, + createEoa: () => { + const wallet = ethers.Wallet.createRandom(); + return { privateKey: wallet.privateKey, address: wallet.address }; + }, + generateProof: (privateKey) => generateEthAuthProof(privateKey), + getAuthToken, + createProject, + getDefaultAccessKey + }; +} + +/** Provision a Builder project + access key unless one already exists. Never throws. */ +export async function ensureBuilderAccessKey( + walletAddress: string, + deps: ProvisionDeps +): Promise { + try { + const existing = await deps.loadBuilderConfig(); + if (existing?.accessKey) return { provisioned: false, reason: 'existing' }; + } catch { + // An unreadable config is treated as absent; provisioning may repair it. + } + + let eoa: { privateKey: string; address: string }; + try { + eoa = deps.createEoa(); + } catch (error) { + return { provisioned: false, reason: `eoa: ${msg(error)}` }; + } + + let jwt: string; + try { + const proof = await deps.generateProof(eoa.privateKey); + jwt = await deps.getAuthToken(proof); + } catch (error) { + return { provisioned: false, reason: `auth: ${msg(error)}` }; + } + + const projectName = `polygon-agent-${walletAddress.slice(2, 10).toLowerCase()}`; + + let projectId: number; + try { + const project = await deps.createProject(projectName, jwt); + projectId = project.id; + } catch (error) { + return { provisioned: false, reason: `project: ${msg(error)}` }; + } + + try { + const accessKey = await deps.getDefaultAccessKey(projectId, jwt); + await deps.saveBuilderConfig({ + privateKey: eoa.privateKey, + eoaAddress: eoa.address, + accessKey, + projectId + }); + return { provisioned: true }; + } catch (error) { + return { provisioned: false, reason: `access-key: ${msg(error)}` }; + } +} diff --git a/packages/polygon-agent-cli/src/lib/dapp-client.ts b/packages/polygon-agent-cli/src/lib/dapp-client.ts deleted file mode 100644 index 6c342ec..0000000 --- a/packages/polygon-agent-cli/src/lib/dapp-client.ts +++ /dev/null @@ -1,414 +0,0 @@ -import fs from 'node:fs'; -import os from 'node:os'; -import path from 'node:path'; - -import type { CliState } from '@0xsequence/dapp-client-cli/state'; - -import { DappClient, TransportMode, jsonRevivers } from '@0xsequence/dapp-client'; -import { isNativeFeeOption } from '@0xsequence/dapp-client-cli/fee-utils'; -import { StateManager } from '@0xsequence/dapp-client-cli/state'; -import { FileSequenceStorage, FileSessionStorage } from '@0xsequence/dapp-client-cli/storage'; - -import { loadWalletSession } from './storage.ts'; - -const STORAGE_DIR = path.join(os.homedir(), '.polygon-agent'); -const DEFAULT_WALLET_URL = 'https://acme-wallet.ecosystem-demo.xyz'; - -interface Transaction { - to: `0x${string}` | string; - value?: bigint | number; - data: string; -} - -interface DappClientTxParams { - walletName: string; - chainId: number; - transactions: Transaction[]; - broadcast: boolean; - preferNativeFee?: boolean; -} - -interface DappClientTxResult { - walletAddress: string; - txHash?: string; - dryRun?: boolean; - feeOptionUsed?: unknown; -} - -// Install fetch logger for debugging network issues -let fetchLoggerInstalled = false; -function installFetchLogger(): void { - if (fetchLoggerInstalled) return; - const enabled = ['1', 'true', 'yes'].includes( - String( - process.env.SEQ_ECO_DEBUG_FETCH || process.env.POLYGON_AGENT_DEBUG_FETCH || '' - ).toLowerCase() - ); - if (!enabled) return; - fetchLoggerInstalled = true; - - const logPath = - process.env.POLYGON_AGENT_FETCH_LOG_PATH || path.join(STORAGE_DIR, 'fetch-debug.log'); - fs.mkdirSync(path.dirname(logPath), { recursive: true }); - - const origFetch = globalThis.fetch; - if (typeof origFetch !== 'function') return; - - const redact = (s: string) => String(s).slice(0, 40000); - const log = (line: string) => - fs.appendFileSync(logPath, `[${new Date().toISOString()}] ${line}\n`, 'utf8'); - - globalThis.fetch = async (input: string | URL | Request, init: RequestInit = {}) => { - const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url; - const method = init?.method || 'GET'; - const bodyPreview = init?.body ? redact(String(init.body)) : ''; - log(`→ ${method} ${url}`); - if (bodyPreview) log(` req.body=${bodyPreview}`); - try { - const res = await origFetch(input, init); - let resText = ''; - try { - resText = redact(await res.clone().text()); - } catch (e) { - resText = `[unreadable: ${(e as Error)?.message || e}]`; - } - log(`← ${res.status} ${method} ${url}`); - if (resText) log(` res.body=${resText}`); - return res; - } catch (e) { - log(`✖ fetch threw: ${method} ${url} :: ${(e as Error)?.stack || e}`); - throw e; - } - }; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - if ((globalThis as any).window) (globalThis as any).window.fetch = globalThis.fetch; - log(`fetch logger enabled; logPath=${logPath}`); -} - -function getPassphrase(): string { - if (process.env.DAPP_CLIENT_CLI_PASSPHRASE) { - return process.env.DAPP_CLIENT_CLI_PASSPHRASE; - } - - const keyPath = path.join(STORAGE_DIR, '.encryption-key'); - if (!fs.existsSync(keyPath)) { - throw new Error( - 'Missing ~/.polygon-agent/.encryption-key — run "polygon-agent wallet create" first' - ); - } - - const keyBuf = fs.readFileSync(keyPath); - return keyBuf.slice(0, 16).toString('hex'); -} - -function statePathFor(walletName: string): string { - const dir = path.join(STORAGE_DIR, 'state', 'dapp-client-cli'); - fs.mkdirSync(dir, { recursive: true, mode: 0o700 }); - return path.join(dir, `${walletName}.state.enc`); -} - -async function syncStateAndGetStorage({ - walletName, - chainId -}: { - walletName: string; - chainId: number; -}) { - const session = await loadWalletSession(walletName); - if (!session) { - throw new Error(`Wallet not found: ${walletName}`); - } - - const walletAddress = session.walletAddress as `0x${string}`; - - const explicitRaw = session.explicitSession; - if (!explicitRaw) { - throw new Error('Missing explicit session. Re-run wallet start-session.'); - } - - const explicitSession = JSON.parse(explicitRaw, jsonRevivers); - if (!explicitSession?.pk) { - throw new Error('Stored explicit session is missing pk; re-link wallet'); - } - - const deadline = explicitSession?.config?.deadline; - if (deadline) { - const deadlineSec = typeof deadline === 'bigint' ? Number(deadline) : Number(deadline); - const nowSec = Math.floor(Date.now() / 1000); - if (Number.isFinite(deadlineSec) && deadlineSec <= nowSec) { - throw new Error( - `Explicit session has expired (deadline ${deadlineSec}). Re-link wallet to mint a fresh session.` - ); - } - } - - const passphrase = getPassphrase(); - const statePath = statePathFor(walletName); - - const stateManager = new StateManager(statePath, passphrase); - const storage = new FileSequenceStorage(stateManager, { - suppressPendingRedirect: true - }); - const sessionStorage = new FileSessionStorage(stateManager); - - const walletUrl = process.env.SEQUENCE_ECOSYSTEM_WALLET_URL || DEFAULT_WALLET_URL; - const origin = process.env.SEQUENCE_DAPP_ORIGIN || 'https://agentconnect.polygon.technology'; - const projectAccessKey = session.projectAccessKey || process.env.SEQUENCE_PROJECT_ACCESS_KEY; - if (!projectAccessKey) - throw new Error('Missing SEQUENCE_PROJECT_ACCESS_KEY (not in wallet session or environment)'); - - const keymachineUrl = process.env.SEQUENCE_KEYMACHINE_URL || 'https://keymachine.sequence.app'; - const nodesUrl = process.env.SEQUENCE_NODES_URL || 'https://nodes.sequence.app/{network}'; - const relayerUrl = process.env.SEQUENCE_RELAYER_URL || 'https://{network}-relayer.sequence.app'; - - await stateManager.update((state: CliState) => { - state.config.walletUrl = walletUrl; - state.config.origin = origin; - state.config.projectAccessKey = projectAccessKey; - state.config.keymachineUrl = keymachineUrl; - state.config.nodesUrl = nodesUrl; - state.config.relayerUrl = relayerUrl; - state.config.transportMode = 'redirect'; - - state.storage.pendingRedirect = false; - state.storage.tempSessionPk = null; - state.storage.pendingRequest = null; - state.storage.explicitSessions = []; - state.storage.implicitSession = null; - - state.storage.sessionlessConnection = { walletAddress }; - state.storage.sessionlessConnectionSnapshot = { walletAddress }; - }); - - const implicitMeta = session.implicitMeta ? JSON.parse(session.implicitMeta, jsonRevivers) : {}; - - // guard is stored as a JSON string (serialized with jsonReplacers) — parse it back - // so moduleAddresses is a proper Map<> rather than a plain object - const guardRaw = implicitMeta.guard; - const guard = - guardRaw && typeof guardRaw === 'string' - ? JSON.parse(guardRaw, jsonRevivers) - : (guardRaw ?? undefined); - - await storage.saveExplicitSession({ - pk: explicitSession.pk as `0x${string}`, - walletAddress, - chainId, - loginMethod: implicitMeta.loginMethod ?? explicitSession.loginMethod, - userEmail: implicitMeta.userEmail ?? explicitSession.userEmail, - guard - }); - - await stateManager.update((state: CliState) => { - state.storage.sessionlessConnection = { - walletAddress, - loginMethod: implicitMeta.loginMethod ?? explicitSession.loginMethod, - userEmail: implicitMeta.userEmail ?? explicitSession.userEmail, - guard - }; - state.storage.sessionlessConnectionSnapshot = { - walletAddress, - loginMethod: implicitMeta.loginMethod ?? explicitSession.loginMethod, - userEmail: implicitMeta.userEmail ?? explicitSession.userEmail, - guard - }; - }); - - if (session.implicitPk && session.implicitAttestation && session.implicitIdentitySig) { - const implicitAttestation = JSON.parse(session.implicitAttestation, jsonRevivers); - const implicitIdentitySignature = JSON.parse(session.implicitIdentitySig, jsonRevivers); - await storage.saveImplicitSession({ - pk: session.implicitPk as `0x${string}`, - walletAddress, - chainId, - attestation: implicitAttestation, - identitySignature: implicitIdentitySignature - }); - } - - await storage.setPendingRedirectRequest(false); - await storage.getAndClearPendingRequest(); - await storage.getAndClearTempSessionPk(); - - await sessionStorage.removeItem(''); - - return { - storage, - sessionStorage, - walletAddress, - walletUrl, - origin, - projectAccessKey, - keymachineUrl, - nodesUrl, - relayerUrl - }; -} - -export async function runDappClientTx({ - walletName, - chainId, - transactions, - broadcast, - preferNativeFee -}: DappClientTxParams): Promise { - const { - storage, - sessionStorage, - walletAddress, - walletUrl, - origin, - projectAccessKey, - keymachineUrl, - nodesUrl, - relayerUrl - } = await syncStateAndGetStorage({ walletName, chainId }); - - // Node.js polyfill - // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (!(globalThis as any).window) (globalThis as any).window = { fetch: globalThis.fetch }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - else if (!(globalThis as any).window.fetch) (globalThis as any).window.fetch = globalThis.fetch; - - installFetchLogger(); - - const client = new DappClient(walletUrl, origin, projectAccessKey, { - transportMode: TransportMode.REDIRECT, - keymachineUrl, - nodesUrl, - relayerUrl, - sequenceStorage: storage, - sequenceSessionStorage: sessionStorage, - canUseIndexedDb: false - }); - - await client.initialize(); - if (!client.isInitialized) throw new Error('Client not initialized'); - - if (!broadcast) { - const bigintReplacer = (_k: string, v: unknown) => (typeof v === 'bigint' ? v.toString() : v); - console.log( - JSON.stringify( - { ok: true, dryRun: true, walletName, walletAddress, transactions }, - bigintReplacer, - 2 - ) - ); - return { walletAddress, dryRun: true }; - } - - const debugFee = ['1', 'true', 'yes'].includes( - String( - process.env.SEQ_ECO_DEBUG_FEE_OPTIONS || process.env.POLYGON_AGENT_DEBUG_FEE || '' - ).toLowerCase() - ); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let feeOpt: any; - - if (preferNativeFee) { - try { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const feeOptions = await client.getFeeOptions(chainId, transactions as any); - if (debugFee) console.error(JSON.stringify({ debug: 'feeOptions', feeOptions }, null, 2)); - const nativeOpt = (feeOptions || []).find(isNativeFeeOption); - if (nativeOpt) feeOpt = nativeOpt; - } catch { - // Fall through to ERC20 fee path - } - } - - if (!feeOpt) { - try { - const feeTokens = await client.getFeeTokens(chainId); - if (debugFee) console.error(JSON.stringify({ debug: 'feeTokens', feeTokens }, null, 2)); - - const paymentAddress = feeTokens?.paymentAddress; - const tokens = Array.isArray(feeTokens?.tokens) ? feeTokens.tokens : []; - - const USDC_POLYGON = '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359'; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let erc20Token: any = null; - if (tokens.length > 0) { - try { - const { SequenceIndexer } = await import('@0xsequence/indexer'); - const chainIndexerUrl = `https://polygon-indexer.sequence.app`; - const indexerKey = process.env.SEQUENCE_INDEXER_ACCESS_KEY || projectAccessKey; - const indexer = new SequenceIndexer(chainIndexerUrl, indexerKey); - const balRes = await indexer.getTokenBalances({ - accountAddress: walletAddress, - includeMetadata: false - }); - const heldAddresses = new Set( - (balRes?.balances || []).map((b: { contractAddress?: string }) => - b.contractAddress?.toLowerCase() - ) - ); - const heldFeeTokens = tokens.filter( - (t: { contractAddress?: string }) => - t?.contractAddress && heldAddresses.has(t.contractAddress.toLowerCase()) - ); - erc20Token = - heldFeeTokens.find( - (t: { contractAddress?: string }) => t.contractAddress?.toLowerCase() === USDC_POLYGON - ) || - heldFeeTokens.find((t: { symbol?: string }) => t?.symbol === 'USDC') || - heldFeeTokens[0] || - null; - } catch { - // Indexer unavailable — fall back to symbol matching - } - if (!erc20Token) { - erc20Token = - tokens.find( - (t: { contractAddress?: string }) => - t?.contractAddress?.toLowerCase() === USDC_POLYGON - ) || - tokens.find( - (t: { contractAddress?: string; symbol?: string }) => - t?.contractAddress && t?.symbol === 'USDC' - ) || - tokens.find((t: { contractAddress?: string }) => t?.contractAddress) || - null; - } - } - - if (paymentAddress && erc20Token) { - const decimals = typeof erc20Token.decimals === 'number' ? erc20Token.decimals : 6; - // 0.1 token units as fee cap (e.g. 0.1 USDC = 100000 for 6 decimals) - const feeValue = decimals >= 1 ? 10 ** (decimals - 1) : 1; - feeOpt = { - token: erc20Token, - to: paymentAddress, - value: String(feeValue), - gasLimit: 0 - }; - if (debugFee) console.error(JSON.stringify({ debug: 'selectedFee', feeOpt }, null, 2)); - } - } catch (e) { - if (debugFee) - console.error( - JSON.stringify({ debug: 'getFeeTokens failed', error: (e as Error)?.message }, null, 2) - ); - } - } - - if (!feeOpt) { - try { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const feeOptions = await client.getFeeOptions(chainId, transactions as any); - feeOpt = feeOptions?.[0]; - } catch (e) { - throw new Error( - `Unable to pay gas: wallet has no POL (native gas) and no usable fee token. ` + - `Fund with POL: polygon-agent fund, or enable USDC gas: polygon-agent wallet create --usdc-limit 5. ` + - `Technical: ${(e as Error)?.message}` - ); - } - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const txHash = await client.sendTransaction(chainId, transactions as any, feeOpt); - return { walletAddress, txHash, feeOptionUsed: feeOpt }; -} diff --git a/packages/polygon-agent-cli/src/lib/indexer.ts b/packages/polygon-agent-cli/src/lib/indexer.ts new file mode 100644 index 0000000..eec1e08 --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/indexer.ts @@ -0,0 +1,49 @@ +// Funded check for the post-login funding step: does the wallet hold any balance +// (native or tokens) on the chain? Routes funded -> dashboard, empty -> funding. +// +// Uses the OMS SDK's own indexer (`oms.indexer.getBalances`, the same call the +// `balances` command uses), which authenticates with the wallet's session — so it +// needs no separate indexer access key and won't misreport a funded wallet as +// empty. Any error returns false so callers fall through to the funding page +// rather than erroring. + +import { findNetworkById } from '@polygonlabs/oms-wallet'; + +import { getOmsClient } from './oms-client.ts'; + +function toBigInt(v: unknown): bigint { + try { + return BigInt((v as string | undefined) || '0'); + } catch { + return 0n; + } +} + +/** True if the wallet holds any native or token balance on `chainId`. */ +export async function isWalletFunded( + walletName: string, + walletAddress: string, + chainId = 137 +): Promise { + try { + const network = findNetworkById(chainId); + if (!network) return false; + + const oms = getOmsClient(walletName); + const res = await oms.indexer.getBalances({ + walletAddress, + networks: [network], + includeMetadata: true + }); + + if (toBigInt(res.nativeBalances?.[0]?.balance) > 0n) return true; + for (const b of res.balances ?? []) { + if (toBigInt((b as { balance?: string }).balance) > 0n) return true; + } + return false; + } catch { + // Session expired / indexer error / unsupported chain: treat as empty so we + // show funding rather than throwing. + return false; + } +} diff --git a/packages/polygon-agent-cli/src/lib/login-relay-client.ts b/packages/polygon-agent-cli/src/lib/login-relay-client.ts new file mode 100644 index 0000000..b5ee3d2 --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/login-relay-client.ts @@ -0,0 +1,51 @@ +// HTTP client for the relay's /api/login pairing routes (packages/oidc-relay). +// Produces the `relay` dependency for runBrowserLogin. The Google OAuth +// callback itself is now handled by the OMS relay, not this client; the +// pairing session only ever carries session/action/status. + +import type { BrowserLoginDeps, LoginAction, LoginStatus } from './browser-login.ts'; + +export function makeLoginRelay(relayBase: string): BrowserLoginDeps['relay'] { + return { + async registerSession(session: string): Promise { + const res = await fetch(`${relayBase}/api/login/register`, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ session }) + }); + if (!res.ok && res.status !== 204) { + throw new Error( + `Relay register failed (${res.status}). Check POLYGON_AGENT_OIDC_RELAY / --relay-url, or use --local.` + ); + } + }, + + async nextAction(session: string): Promise { + const res = await fetch( + `${relayBase}/api/login/next-action?session=${encodeURIComponent(session)}` + ); + if (!res.ok) throw new Error(`Relay poll failed (${res.status})`); + const data = (await res.json()) as { state: string; action?: LoginAction }; + if (data.state === 'expired') { + throw new Error('Login session expired before completion. Re-run `wallet login`.'); + } + return data.state === 'action' && data.action ? data.action : null; + }, + + async setStatus(session: string, status: LoginStatus): Promise { + // Best effort: the status channel is a courtesy signal to the page, not + // the source of truth (the CLI's own return value is that). A relay + // hiccup or an expired session (the DO now 410s once it is no longer + // armed) must not fail a login that has already completed. + try { + await fetch(`${relayBase}/api/login/status`, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ session, status }) + }); + } catch { + // network error; nothing to do, the CLI result stands on its own. + } + } + }; +} diff --git a/packages/polygon-agent-cli/src/lib/oidc-callback-server.ts b/packages/polygon-agent-cli/src/lib/oidc-callback-server.ts new file mode 100644 index 0000000..122a95e --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/oidc-callback-server.ts @@ -0,0 +1,118 @@ +// Short-lived localhost callback server for the browser OIDC login flow. +// +// The OMS OIDC redirect sends the user to Google; after login the relay bounces +// the browser back to a loopback URL we host here. We capture that single +// callback request, hand the full URL back to the caller (who passes it to +// completeOidcRedirectAuth), serve a "you can close this tab" page, and shut +// down. The server binds to 127.0.0.1 on an ephemeral port and `unref()`s so it +// never keeps the CLI process alive on its own. + +import type { AddressInfo } from 'node:net'; + +import http from 'node:http'; + +export interface OidcCallbackServer { + /** The loopback redirect URI to pass to startOidcRedirectAuth. */ + redirectUri: string; + /** Resolves with the full callback URL once the browser hits /callback. */ + waitForCallbackUrl: Promise; + /** Idempotently stop the server. */ + close(): void; +} + +const SUCCESS_HTML = `Login complete + +

You're signed in

+

Login complete. You can close this tab and return to your terminal.

`; + +const ERROR_HTML = `Login failed + +

Login failed

+

Something went wrong. Return to your terminal for details.

`; + +/** + * Start the loopback callback server. Resolves once it's listening, with the + * derived redirectUri and a promise that fires on the callback. + * + * @param opts.port Explicit port, or 0/undefined for an OS-assigned one. + * @param opts.timeoutMs Reject waitForCallbackUrl if no callback arrives in time. + */ +export function startOidcCallbackServer(opts: { + port?: number; + timeoutMs: number; +}): Promise { + return new Promise((resolveServer, rejectServer) => { + let settled = false; + let resolveUrl!: (url: string) => void; + let rejectUrl!: (err: Error) => void; + const waitForCallbackUrl = new Promise((res, rej) => { + resolveUrl = res; + rejectUrl = rej; + }); + + const server = http.createServer((req, res) => { + const path = (req.url ?? '').split('?')[0]; + // Ignore favicon/prefetch and anything that isn't the callback so a stray + // browser request doesn't prematurely resolve the flow. + if (path !== '/callback') { + res.statusCode = 204; + res.end(); + return; + } + const isError = (req.url ?? '').includes('error='); + res.statusCode = 200; + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end(isError ? ERROR_HTML : SUCCESS_HTML, () => { + // Resolve with the full absolute URL the SDK expects (it parses + // code/state/error from the query string). + const port = (server.address() as AddressInfo).port; + if (!settled) { + settled = true; + resolveUrl(`http://localhost:${port}${req.url}`); + } + close(); + }); + }); + + const timer = setTimeout(() => { + if (!settled) { + settled = true; + rejectUrl(new Error('Browser login timed out. Re-run, or use `wallet login`.')); + close(); + } + }, opts.timeoutMs); + + let closed = false; + function close(): void { + if (closed) return; + closed = true; + clearTimeout(timer); + server.close(); + } + + server.on('error', (err) => { + // Surface listen errors (e.g. EADDRINUSE on an explicit --port) clearly. + if (!settled) { + settled = true; + rejectUrl(err); + } + rejectServer(err); + }); + + server.listen(opts.port ?? 0, '127.0.0.1', () => { + const port = (server.address() as AddressInfo).port; + server.unref(); // never block process exit on the listener + resolveServer({ + redirectUri: `http://localhost:${port}/callback`, + waitForCallbackUrl, + close + }); + }); + }); +} diff --git a/packages/polygon-agent-cli/src/lib/oms-client.ts b/packages/polygon-agent-cli/src/lib/oms-client.ts new file mode 100644 index 0000000..9ee582a --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/oms-client.ts @@ -0,0 +1,65 @@ +// OMSWallet factory — builds a per-process, per-wallet OMS V3 client backed +// by file storage + a persisted credential signer, so sessions survive restarts. + +import { EthereumPrivateKeyCredentialSigner, OMSWallet } from '@polygonlabs/oms-wallet'; + +import { FileStorageManager, loadOrCreateCredentialKey } from './oms-storage.ts'; +import { loadOmsConfig } from './storage.ts'; + +const cache = new Map(); + +/** + * Get (or build) the OMSWallet for a wallet name. Cached per-process so repeated + * calls within one CLI invocation reuse the same client + storage handle. + * + * Reads publishableKey + projectId from env or builder.json (loadOmsConfig), + * falling back to the baked-in default publishable key. + */ +export function getOmsClient(walletName: string): OMSWallet { + const cached = cache.get(walletName); + if (cached) return cached; + + const cfg = loadOmsConfig(); + + const credentialSigner = new EthereumPrivateKeyCredentialSigner( + loadOrCreateCredentialKey(walletName) + ); + + // The publishableKey alone identifies the project. `redirectAuthStorage` is + // REQUIRED for the OIDC browser flow: in Node the SDK has no sessionStorage + // to fall back to and throws without it. We back it with a separate file + // store so the transient pending-auth state is isolated from the session + // store (and the email-login/tx paths simply ignore it). + const oms = new OMSWallet({ + publishableKey: cfg.publishableKey, + storage: new FileStorageManager(walletName), + redirectAuthStorage: new FileStorageManager(walletName, 'redirect-store'), + credentialSigner + }); + + cache.set(walletName, oms); + return oms; +} + +// Baked-in defaults for the browser-login flow so `wallet login` needs no env +// vars. Production domains, provisioned by the oidc-relay and agentconnect-ui +// deploys on merge to main. Override per environment (or to test against +// staging) with POLYGON_AGENT_OIDC_RELAY / POLYGON_AGENT_LOGIN_UI. +const DEFAULT_OIDC_RELAY = 'https://oidc-relay.polygon.technology'; +const DEFAULT_LOGIN_UI = 'https://agentconnect.polygon.technology'; + +/** + * Base URL of our login pairing relay (packages/oidc-relay). Read from + * POLYGON_AGENT_OIDC_RELAY with a production default; `--relay-url` overrides + * per-run. Trailing slash trimmed so callers can append `/api/...` cleanly. + */ +export function oidcRelayBaseUrl(): string { + const v = process.env.POLYGON_AGENT_OIDC_RELAY; + return v ? v.replace(/\/+$/, '') : DEFAULT_OIDC_RELAY; +} + +/** Base URL of the agentconnect login page. POLYGON_AGENT_LOGIN_UI overrides. */ +export function loginUiBaseUrl(): string { + const v = process.env.POLYGON_AGENT_LOGIN_UI; + return v ? v.replace(/\/+$/, '') : DEFAULT_LOGIN_UI; +} diff --git a/packages/polygon-agent-cli/src/lib/oms-config.test.ts b/packages/polygon-agent-cli/src/lib/oms-config.test.ts new file mode 100644 index 0000000..47a3bc2 --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/oms-config.test.ts @@ -0,0 +1,102 @@ +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; + +import { afterEach, describe, expect, it, vi } from 'vitest'; + +async function freshStorage(home: string) { + vi.resetModules(); + vi.stubEnv('HOME', home); + return await import('./storage.ts'); +} + +describe('loadOmsConfig resolution order', () => { + afterEach(() => { + vi.unstubAllEnvs(); + vi.resetModules(); + }); + + it('falls back to the baked-in default when neither env nor file exist', async () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), 'pa-home-')); + vi.stubEnv('OMS_PUBLISHABLE_KEY', ''); + const storage = await freshStorage(home); + const cfg = storage.loadOmsConfig(); + expect(cfg.publishableKey).toBe(storage.DEFAULT_OMS_PUBLISHABLE_KEY); + expect(cfg.publishableKey.startsWith('pk_')).toBe(true); + }); + + it('prefers builder.json over the default', async () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), 'pa-home-')); + fs.mkdirSync(path.join(home, '.polygon-agent'), { recursive: true }); + fs.writeFileSync( + path.join(home, '.polygon-agent', 'builder.json'), + JSON.stringify({ publishableKey: 'pk_test_fromfile' }) + ); + vi.stubEnv('OMS_PUBLISHABLE_KEY', ''); + const storage = await freshStorage(home); + expect(storage.loadOmsConfig().publishableKey).toBe('pk_test_fromfile'); + }); + + it('prefers the env var over everything', async () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), 'pa-home-')); + vi.stubEnv('OMS_PUBLISHABLE_KEY', 'pk_test_fromenv'); + const storage = await freshStorage(home); + expect(storage.loadOmsConfig().publishableKey).toBe('pk_test_fromenv'); + }); +}); + +describe('saveBuilderConfig merging', () => { + afterEach(() => { + vi.unstubAllEnvs(); + vi.resetModules(); + }); + + it('merges new fields into builder.json instead of clobbering it', async () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), 'pa-home-')); + const configDir = path.join(home, '.polygon-agent'); + fs.mkdirSync(configDir, { recursive: true }); + const configPath = path.join(configDir, 'builder.json'); + fs.writeFileSync( + configPath, + JSON.stringify({ publishableKey: 'pk_test_keep', polymarketPrivateKey: 'enc_keep' }) + ); + + const storage = await freshStorage(home); + await storage.saveBuilderConfig({ + privateKey: '0xabc', + eoaAddress: '0x1', + accessKey: 'AQ_new', + projectId: 7 + }); + + const data = JSON.parse(fs.readFileSync(configPath, 'utf8')); + expect(data.publishableKey).toBe('pk_test_keep'); + expect(data.polymarketPrivateKey).toBe('enc_keep'); + expect(data.accessKey).toBe('AQ_new'); + expect(data.projectId).toBe(7); + }); + + it('loadBuilderConfigRaw reads the accessKey without decrypting, and is null-safe', async () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), 'pa-home-')); + const configDir = path.join(home, '.polygon-agent'); + fs.mkdirSync(configDir, { recursive: true }); + const configPath = path.join(configDir, 'builder.json'); + fs.writeFileSync( + configPath, + JSON.stringify({ publishableKey: 'pk_test_keep', polymarketPrivateKey: 'enc_keep' }) + ); + + const storage = await freshStorage(home); + await storage.saveBuilderConfig({ + privateKey: '0xabc', + eoaAddress: '0x1', + accessKey: 'AQ_new', + projectId: 7 + }); + expect(storage.loadBuilderConfigRaw()).toEqual({ accessKey: 'AQ_new' }); + + const emptyHome = fs.mkdtempSync(path.join(os.tmpdir(), 'pa-home-')); + const emptyStorage = await freshStorage(emptyHome); + expect(emptyStorage.loadBuilderConfigRaw()).toBeNull(); + }); +}); diff --git a/packages/polygon-agent-cli/src/lib/oms-storage.ts b/packages/polygon-agent-cli/src/lib/oms-storage.ts new file mode 100644 index 0000000..df2f255 --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/oms-storage.ts @@ -0,0 +1,98 @@ +// File-backed StorageManager + credential-key persistence for the OMS SDK. +// +// The OMS typescript-sdk persists its wallet session through a StorageManager +// (a simple get/set/delete string KV) and signs requests with a CredentialSigner. +// For a headless CLI we: +// - back the StorageManager with encrypted files under ~/.polygon-agent/oms//store/ +// - persist the EthereumPrivateKeyCredentialSigner's private key to disk (encrypted) +// so a session survives across CLI invocations (verified in the Phase 0 spike). + +import { randomBytes } from 'node:crypto'; +import fs from 'node:fs'; +import path from 'node:path'; + +import type { StorageManager } from '@polygonlabs/oms-wallet'; + +import type { CipherData } from './storage.ts'; + +import { decrypt, encrypt, omsWalletDir } from './storage.ts'; + +// Encode a storage key into a filesystem-safe filename. +function keyToFile(dir: string, key: string): string { + const safe = Buffer.from(key).toString('hex'); + return path.join(dir, `${safe}.enc`); +} + +/** + * Synchronous, encrypted, file-backed StorageManager scoped to one wallet name. + * Each entry is an AES-256-GCM blob written under //. + * `subdir` defaults to 'store' (the session store); the OIDC redirect flow uses + * a separate 'redirect-store' so its transient pending state stays isolated. + */ +export class FileStorageManager implements StorageManager { + private dir: string; + + constructor(walletName: string, subdir = 'store') { + this.dir = path.join(omsWalletDir(walletName), subdir); + if (!fs.existsSync(this.dir)) fs.mkdirSync(this.dir, { recursive: true, mode: 0o700 }); + } + + get(key: string): string | null { + const file = keyToFile(this.dir, key); + if (!fs.existsSync(file)) return null; + try { + const cipher = JSON.parse(fs.readFileSync(file, 'utf8')) as CipherData; + return decrypt(cipher); + } catch { + return null; + } + } + + set(key: string, value: string): void { + const file = keyToFile(this.dir, key); + fs.writeFileSync(file, JSON.stringify(encrypt(value)), { mode: 0o600 }); + } + + delete(key: string): void { + const file = keyToFile(this.dir, key); + // Unlink directly and ignore "already gone" rather than check-then-delete. + try { + fs.unlinkSync(file); + } catch (err) { + if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err; + } + } +} + +const CREDENTIAL_KEY_FILE = 'credential.key.enc'; + +/** + * Load the persisted credential private key for a wallet, or generate + persist + * a new one. Returns the raw 32-byte key for EthereumPrivateKeyCredentialSigner. + */ +export function loadOrCreateCredentialKey(walletName: string): Uint8Array { + const file = path.join(omsWalletDir(walletName), CREDENTIAL_KEY_FILE); + // Read-or-create without a check-then-use race: try to read; on ENOENT create + // the file exclusively (wx), and if a concurrent run won that race, loop back + // and read the key it wrote. + for (;;) { + try { + const cipher = JSON.parse(fs.readFileSync(file, 'utf8')) as CipherData; + return Uint8Array.from(Buffer.from(decrypt(cipher), 'hex')); + } catch (err) { + if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err; + } + const keyHex = Buffer.from(randomBytes(32)).toString('hex'); + try { + fs.writeFileSync(file, JSON.stringify(encrypt(keyHex)), { mode: 0o600, flag: 'wx' }); + return Uint8Array.from(Buffer.from(keyHex, 'hex')); + } catch (err) { + if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err; + } + } +} + +/** True if a credential key has already been persisted for this wallet. */ +export function hasCredentialKey(walletName: string): boolean { + return fs.existsSync(path.join(omsWalletDir(walletName), CREDENTIAL_KEY_FILE)); +} diff --git a/packages/polygon-agent-cli/src/lib/oms-tx.ts b/packages/polygon-agent-cli/src/lib/oms-tx.ts new file mode 100644 index 0000000..7c50657 --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/oms-tx.ts @@ -0,0 +1,126 @@ +// OMS transaction primitive — drop-in replacement for runDappClientTx. +// +// Keeps the exact same { walletName, chainId, transactions[], broadcast, preferNativeFee } +// interface and { walletAddress, txHash?, dryRun?, feeOptionUsed? } result so the +// existing command call sites need only swap which implementation they call (via +// the runTx dispatch). Internally maps onto oms.wallet.sendTransaction. + +import type { FeeOptionWithBalance } from '@polygonlabs/oms-wallet'; + +import { findNetworkById, isOMSWalletError, TransactionMode } from '@polygonlabs/oms-wallet'; + +import { getOmsClient } from './oms-client.ts'; + +export interface OmsTxTransaction { + to: `0x${string}` | string; + value?: bigint | number; + data: string; +} + +export interface OmsTxParams { + walletName: string; + chainId: number; + transactions: OmsTxTransaction[]; + broadcast: boolean; + preferNativeFee?: boolean; +} + +export interface OmsTxResult { + walletAddress: string; + txHash?: string; + dryRun?: boolean; + feeOptionUsed?: unknown; +} + +const USDC_POLYGON = '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359'; + +// Build a selectFeeOption callback mirroring the legacy fee logic: +// prefer native gas if requested, else prefer USDC, always gated on affordability. +function makeFeeSelector(preferNativeFee: boolean) { + return (opts: FeeOptionWithBalance[]) => { + const usable = opts.filter( + (o) => o.availableRaw != null && BigInt(o.availableRaw) >= BigInt(o.feeOption.value) + ); + const isNative = (o: FeeOptionWithBalance) => + !o.feeOption.token.contractAddress || + o.feeOption.token.symbol?.toUpperCase() === 'POL' || + o.feeOption.token.symbol?.toUpperCase() === 'ETH'; + + let pick: FeeOptionWithBalance | undefined; + if (preferNativeFee) pick = usable.find(isNative); + if (!pick) { + pick = + usable.find((o) => o.feeOption.token.contractAddress?.toLowerCase() === USDC_POLYGON) ?? + usable.find((o) => o.feeOption.token.symbol?.toUpperCase().includes('USDC')) ?? + (preferNativeFee ? undefined : usable.find(isNative)) ?? + usable[0]; + } + if (!pick) { + throw new Error( + 'Unable to pay gas: wallet has no native token and no usable fee token. ' + + 'Fund with POL (agent fund), or hold USDC for fees.' + ); + } + return { token: pick.feeOption.token.symbol }; + }; +} + +export async function runOmsTx(params: OmsTxParams): Promise { + const { walletName, chainId, transactions, broadcast, preferNativeFee = false } = params; + + const oms = getOmsClient(walletName); + const walletAddress = oms.wallet.walletAddress; + if (!walletAddress) { + throw new Error(`No active session for wallet '${walletName}'. Run: agent wallet login`); + } + + // Dry-run: print the same JSON shape the legacy primitive produced and return. + if (!broadcast) { + const bigintReplacer = (_k: string, v: unknown) => (typeof v === 'bigint' ? v.toString() : v); + console.log( + JSON.stringify( + { ok: true, dryRun: true, walletName, walletAddress, transactions }, + bigintReplacer, + 2 + ) + ); + return { walletAddress, dryRun: true }; + } + + const network = findNetworkById(chainId); + if (!network) throw new Error(`Unsupported chainId for OMS: ${chainId}`); + + const selectFeeOption = makeFeeSelector(preferNativeFee); + + // OMS sendTransaction takes a single tx. For multi-tx bundles (only `deposit` + // sends 2: approve + supply) we submit sequentially. NON-ATOMIC: if the second + // fails, the first has already landed. Return the last tx's hash. + let lastTxHash: string | undefined; + let lastFee: unknown; + for (const tx of transactions) { + try { + const res = await oms.wallet.sendTransaction({ + network, + to: tx.to as `0x${string}`, + data: tx.data as `0x${string}`, + value: tx.value != null ? BigInt(tx.value) : 0n, + mode: TransactionMode.Relayer, + waitForStatus: true, + selectFeeOption + }); + lastTxHash = res.txnHash ?? lastTxHash; + } catch (e) { + if ( + isOMSWalletError(e) && + (e.code === 'OMS_SESSION_EXPIRED' || e.code === 'OMS_SESSION_MISSING') + ) { + throw new Error( + `Session expired or missing for wallet '${walletName}'. ` + `Run: agent wallet login` + ); + } + throw e; + } + } + + return { walletAddress, txHash: lastTxHash, feeOptionUsed: lastFee }; +} diff --git a/packages/polygon-agent-cli/src/lib/polymarket.ts b/packages/polygon-agent-cli/src/lib/polymarket.ts index 4f7ecec..0071fbe 100644 --- a/packages/polygon-agent-cli/src/lib/polymarket.ts +++ b/packages/polygon-agent-cli/src/lib/polymarket.ts @@ -1,8 +1,8 @@ // Polymarket integration library — CLOB V2 // Covers: Gamma API (market discovery), CLOB V2 API (trading via @polymarket/clob-client-v2), on-chain ops // -// Architecture: Sequence smart wallet → Polymarket proxy wallet → CLOB -// - Sequence smart wallet funds the Polymarket proxy wallet (USDC.e transfer) +// Architecture: OMS smart wallet → Polymarket proxy wallet → CLOB +// - OMS smart wallet funds the Polymarket proxy wallet (USDC.e transfer) // - Proxy wallet wraps USDC.e → pUSD via CollateralOnramp before trading // - EOA calls proxy.execute([approve, wrap]) to run on-chain ops FROM the proxy wallet // - CLOB orders use maker=proxyWallet, signer=EOA, signatureType=POLY_PROXY diff --git a/packages/polygon-agent-cli/src/lib/relay-client.ts b/packages/polygon-agent-cli/src/lib/relay-client.ts deleted file mode 100644 index c117a28..0000000 --- a/packages/polygon-agent-cli/src/lib/relay-client.ts +++ /dev/null @@ -1,98 +0,0 @@ -// packages/polygon-agent-cli/src/lib/relay-client.ts -import type { - EncryptedPayload, - RelayCreateResponse, - RelayStatusResponse -} from '@polygonlabs/agent-shared'; - -export class RelayClient { - private baseUrl: string; - - constructor(baseUrl: string) { - this.baseUrl = baseUrl; - } - - private cfAccessHeaders(): Record { - // Service token auth (CI / machine clients) - const id = process.env.CF_ACCESS_CLIENT_ID; - const secret = process.env.CF_ACCESS_CLIENT_SECRET; - if (id && secret) { - return { 'CF-Access-Client-Id': id, 'CF-Access-Client-Secret': secret }; - } - // User JWT from `cloudflared access token --app ` - const token = process.env.CF_ACCESS_TOKEN; - if (token) { - return { 'CF-Access-Token': token }; - } - return {}; - } - - /** Register CLI public key with relay. Returns request_id. */ - async createRequest(cliPkHex: string): Promise { - const res = await fetch(`${this.baseUrl}/api/relay/request`, { - method: 'POST', - headers: { 'Content-Type': 'application/json', ...this.cfAccessHeaders() }, - body: JSON.stringify({ cli_pk_hex: cliPkHex }) - }); - if (!res.ok) { - const text = await res.text(); - throw new Error(`Relay createRequest failed (${res.status}): ${text}`); - } - const data = (await res.json()) as RelayCreateResponse; - return data.request_id; - } - - /** Poll until status is "ready" or timeout. Calls onPolling each interval. */ - async waitForReady( - requestId: string, - timeoutMs = 300_000, - intervalMs = 2_000, - onPolling?: () => void - ): Promise { - const deadline = Date.now() + timeoutMs; - while (Date.now() < deadline) { - const res = await fetch(`${this.baseUrl}/api/relay/status/${requestId}`, { - headers: this.cfAccessHeaders() - }); - if (res.status === 404) throw new Error('Relay request not found (expired or invalid)'); - if (!res.ok) throw new Error(`Relay status check failed (${res.status})`); - const data = (await res.json()) as RelayStatusResponse; - if (data.status === 'ready') return; - onPolling?.(); - await new Promise((r) => setTimeout(r, intervalMs)); - } - throw new Error('Timed out waiting for wallet approval (5 minutes)'); - } - - /** Submit code hash and retrieve encrypted payload if correct. */ - async retrieve(requestId: string, codeHashHex: string): Promise { - const res = await fetch(`${this.baseUrl}/api/relay/retrieve/${requestId}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json', ...this.cfAccessHeaders() }, - body: JSON.stringify({ code_hash_hex: codeHashHex }) - }); - - if (res.status === 403) { - const data = (await res.json()) as { attempts_remaining: number }; - throw new RelayCodeError( - `Wrong code. ${data.attempts_remaining} attempt(s) remaining.`, - data.attempts_remaining - ); - } - if (res.status === 410) - throw new RelayCodeError('Too many wrong attempts. Session expired.', 0); - if (!res.ok) throw new Error(`Relay retrieve failed (${res.status})`); - - return (await res.json()) as EncryptedPayload; - } -} - -export class RelayCodeError extends Error { - readonly attemptsRemaining: number; - - constructor(message: string, attemptsRemaining: number) { - super(message); - this.name = 'RelayCodeError'; - this.attemptsRemaining = attemptsRemaining; - } -} diff --git a/packages/polygon-agent-cli/src/lib/storage.ts b/packages/polygon-agent-cli/src/lib/storage.ts index a8bf68f..5f2dd14 100644 --- a/packages/polygon-agent-cli/src/lib/storage.ts +++ b/packages/polygon-agent-cli/src/lib/storage.ts @@ -3,12 +3,10 @@ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; -import type { SessionPayload } from '@polygonlabs/agent-shared'; - const STORAGE_DIR = path.join(os.homedir(), '.polygon-agent'); const ENCRYPTION_KEY_FILE = path.join(STORAGE_DIR, '.encryption-key'); -interface CipherData { +export interface CipherData { iv: string; encrypted: string; authTag: string; @@ -21,26 +19,32 @@ export interface BuilderConfig { projectId: number; } -export interface WalletSession { +/** + * OMS (Open Money Stack) V3 credentials for the typescript-sdk path. + * As of SDK 0.1.0-alpha.4 the publishableKey alone identifies the project; + * omsProjectId is retained as optional for backward compat / display only. + * Stored alongside builder.json so `wallet login` and tx submission can read it. + */ +export interface OmsConfig { + publishableKey: string; + omsProjectId?: string; +} + +/** How a wallet session was established: Google or email, both chosen on the browser login page. */ +export type OmsLoginMethod = 'google' | 'email'; + +/** Pointer record for an OMS wallet (the SDK persists the real session in its StorageManager). */ +export interface OmsWalletPointer { walletAddress: string; - chainId: number; - chain: string; - projectAccessKey: string | null; - explicitSession: string; - sessionPk: string; - sessionConfig?: string; - implicitPk: string; - implicitMeta: string; - implicitAttestation: string; - implicitIdentitySig: string; + loginMethod: OmsLoginMethod; createdAt: string; } -function ensureStorageDir(): void { +export function ensureStorageDir(): void { if (!fs.existsSync(STORAGE_DIR)) { fs.mkdirSync(STORAGE_DIR, { recursive: true, mode: 0o700 }); } - const subdirs = ['wallets', 'requests', 'state/dapp-client-cli']; + const subdirs = ['wallets', 'oms']; for (const dir of subdirs) { const fullPath = path.join(STORAGE_DIR, dir); if (!fs.existsSync(fullPath)) { @@ -49,7 +53,9 @@ function ensureStorageDir(): void { } } -function getEncryptionKey(): Buffer { +export const STORAGE_ROOT = STORAGE_DIR; + +export function getEncryptionKey(): Buffer { ensureStorageDir(); if (fs.existsSync(ENCRYPTION_KEY_FILE)) { @@ -61,7 +67,7 @@ function getEncryptionKey(): Buffer { return key; } -function encrypt(plaintext: string): CipherData { +export function encrypt(plaintext: string): CipherData { const key = getEncryptionKey(); const iv = randomBytes(16); const cipher = createCipheriv('aes-256-gcm', key, iv); @@ -78,7 +84,7 @@ function encrypt(plaintext: string): CipherData { }; } -function decrypt(cipherData: CipherData): string { +export function decrypt(cipherData: CipherData): string { const key = getEncryptionKey(); const iv = Buffer.from(cipherData.iv, 'hex'); const authTag = Buffer.from(cipherData.authTag, 'hex'); @@ -98,12 +104,17 @@ export async function saveBuilderConfig(config: BuilderConfig): Promise { const configPath = path.join(STORAGE_DIR, 'builder.json'); const encryptedKey = encrypt(config.privateKey); - const data = { - privateKey: encryptedKey, - eoaAddress: config.eoaAddress, - accessKey: config.accessKey, - projectId: config.projectId - }; + let data: Record = {}; + try { + data = JSON.parse(fs.readFileSync(configPath, 'utf8')); + } catch { + // File doesn't exist yet, or is unreadable. Start fresh. + } + + data.privateKey = encryptedKey; + data.eoaAddress = config.eoaAddress; + data.accessKey = config.accessKey; + data.projectId = config.projectId; fs.writeFileSync(configPath, JSON.stringify(data, null, 2), { mode: 0o600 @@ -129,99 +140,24 @@ export async function loadBuilderConfig(): Promise { } /** - * Synchronously resolve the project access key. - * Priority: env var → wallet session's stored key → builder.json on disk. - * Returns undefined if none found. + * Read builder.json's accessKey without decrypting the privateKey blob. + * The provisioning short-circuit must honor an existing project even when + * the encrypted privateKey blob is unreadable (e.g. a stale or missing + * encryption key). This reads only the plaintext accessKey field. */ -export function resolveAccessKeySync(sessionKey?: string | null): string | undefined { - if (process.env.SEQUENCE_PROJECT_ACCESS_KEY) return process.env.SEQUENCE_PROJECT_ACCESS_KEY; - if (process.env.SEQUENCE_INDEXER_ACCESS_KEY) return process.env.SEQUENCE_INDEXER_ACCESS_KEY; - if (sessionKey) return sessionKey; +export function loadBuilderConfigRaw(): { accessKey?: string } | null { const configPath = path.join(STORAGE_DIR, 'builder.json'); - if (fs.existsSync(configPath)) { - try { - const data = JSON.parse(fs.readFileSync(configPath, 'utf8')); - if (data.accessKey) return data.accessKey as string; - } catch { - // ignore malformed config - } - } - return undefined; -} - -/** - * Bootstrap: populate SEQUENCE_PROJECT_ACCESS_KEY from builder.json if not already set. - * Call once at CLI startup so all commands can rely on the env var being present. - */ -export function bootstrapAccessKey(): void { - const key = resolveAccessKeySync(); - if (key && !process.env.SEQUENCE_PROJECT_ACCESS_KEY) { - process.env.SEQUENCE_PROJECT_ACCESS_KEY = key; - } - if (key && !process.env.SEQUENCE_INDEXER_ACCESS_KEY) { - process.env.SEQUENCE_INDEXER_ACCESS_KEY = key; - } -} -export async function saveWalletSession(name: string, session: WalletSession): Promise { - ensureStorageDir(); - - const walletPath = path.join(STORAGE_DIR, 'wallets', `${name}.json`); - fs.writeFileSync(walletPath, JSON.stringify(session, null, 2), { - mode: 0o600 - }); -} - -export async function loadWalletSession(name: string): Promise { - const walletPath = path.join(STORAGE_DIR, 'wallets', `${name}.json`); - - if (!fs.existsSync(walletPath)) { + if (!fs.existsSync(configPath)) { return null; } - return JSON.parse(fs.readFileSync(walletPath, 'utf8')); -} - -export interface WalletRequest { - rid: string; - walletName: string; - chain: string; - createdAt: string; - expiresAt: string; - publicKeyB64u: string; - privateKeyB64u: string; - projectAccessKey: string | null; - /** v2: X25519 secret key hex (used with relay-based code flow) */ - cliSkHex?: string; -} - -export async function saveWalletRequest(rid: string, request: WalletRequest): Promise { - ensureStorageDir(); - - // cliSkHex (v2 X25519 secret key) is stored as plaintext here intentionally: - // the file has 0o600 permissions and the key is ephemeral — it is only useful - // during the ~5-minute request window and is deleted after successful import. - const requestPath = path.join(STORAGE_DIR, 'requests', `${rid}.json`); - fs.writeFileSync(requestPath, JSON.stringify(request, null, 2), { - mode: 0o600 - }); -} - -export async function loadWalletRequest(rid: string): Promise { - const requestPath = path.join(STORAGE_DIR, 'requests', `${rid}.json`); - - if (!fs.existsSync(requestPath)) { + try { + const data = JSON.parse(fs.readFileSync(configPath, 'utf8')); + return { accessKey: data.accessKey }; + } catch { return null; } - - return JSON.parse(fs.readFileSync(requestPath, 'utf8')); -} - -export async function deleteWalletRequest(rid: string): Promise { - const requestPath = path.join(STORAGE_DIR, 'requests', `${rid}.json`); - if (fs.existsSync(requestPath)) { - fs.unlinkSync(requestPath); - } } export async function listWallets(): Promise { @@ -263,51 +199,117 @@ export async function loadPolymarketKey(): Promise { try { data = JSON.parse(fs.readFileSync(configPath, 'utf8')); } catch { - throw new Error('No builder config found. Run: polygon-agent setup'); + throw new Error('No builder config found. Run: agent setup'); } if (data.polymarketPrivateKey) return decrypt(data.polymarketPrivateKey as CipherData); if (data.privateKey) return decrypt(data.privateKey as CipherData); - throw new Error( - 'No EOA key found. Run: polygon-agent setup or polygon-agent polymarket set-key ' - ); + throw new Error('No EOA key found. Run: agent setup or agent polymarket set-key '); } -/** Map a v2 SessionPayload into the WalletSession shape. */ -export function sessionPayloadToWalletSession(payload: SessionPayload): WalletSession { - const chainName = resolveChainNameFromId(payload.chain_id); - const implicit = payload.implicit_session; +// ─── OMS (Open Money Stack V3 / typescript-sdk) config + session storage ────── - const implicitMeta = { - guard: implicit?.guard, - loginMethod: implicit?.login_method, - userEmail: implicit?.user_email - }; +/** Directory holding the OMS SDK's per-wallet storage + credential key. */ +export function omsWalletDir(name: string): string { + ensureStorageDir(); + const dir = path.join(STORAGE_DIR, 'oms', name); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true, mode: 0o700 }); + } + return dir; +} - return { - walletAddress: payload.wallet_address, - chainId: payload.chain_id, - chain: chainName, - projectAccessKey: payload.project_access_key ?? null, - explicitSession: JSON.stringify({ pk: payload.session_private_key }), - sessionPk: payload.session_private_key, - sessionConfig: payload.session_config ?? undefined, - implicitPk: implicit?.pk ?? '', - implicitMeta: JSON.stringify(implicitMeta), - implicitAttestation: implicit?.attestation ?? '', - implicitIdentitySig: implicit?.identity_sig ? JSON.stringify(implicit.identity_sig) : '', - createdAt: new Date().toISOString() - }; +/** Persist OMS publishableKey + projectId into builder.json (merged with existing data). */ +export async function saveOmsConfig(config: OmsConfig): Promise { + ensureStorageDir(); + const configPath = path.join(STORAGE_DIR, 'builder.json'); + let data: Record = {}; + try { + data = JSON.parse(fs.readFileSync(configPath, 'utf8')); + } catch { + // start fresh + } + data.publishableKey = config.publishableKey; + data.omsProjectId = config.omsProjectId; + fs.writeFileSync(configPath, JSON.stringify(data, null, 2), { mode: 0o600 }); } -/** Map numeric chainId to chain name string (e.g. 137 → "polygon"). */ -function resolveChainNameFromId(chainId: number): string { - const map: Record = { - 137: 'polygon', - 80002: 'polygon-amoy', - 42161: 'arbitrum', - 10: 'optimism', - 8453: 'base', - 1: 'mainnet' - }; - return map[chainId] ?? String(chainId); +// Default OMS publishable key so `wallet login` works with zero setup. +// Publishable keys are client-embeddable by design; users are wallets inside +// the CLI's shared OMS project. This is the intended production project key +// (the sdbx prefix is just how the project's keys are labeled). Override with +// OMS_PUBLISHABLE_KEY or `setup --oms-publishable-key`. +export const DEFAULT_OMS_PUBLISHABLE_KEY = 'pk_sdbx_01kqfw9zaykks_01kwvkkzs5e2wb6rfas2y2njm8'; + +/** + * Resolve OMS credentials. Priority: env vars → builder.json → baked-in default. + */ +export function loadOmsConfig(): OmsConfig { + // SDK 0.1.0-alpha.4: only the publishableKey is required (it identifies the + // project). omsProjectId is read if present but no longer mandatory. + const envPk = process.env.OMS_PUBLISHABLE_KEY; + const envProj = process.env.SEQUENCE_OMS_PROJECT_ID; + if (envPk) return { publishableKey: envPk, omsProjectId: envProj }; + + const configPath = path.join(STORAGE_DIR, 'builder.json'); + if (fs.existsSync(configPath)) { + try { + const data = JSON.parse(fs.readFileSync(configPath, 'utf8')); + const publishableKey = data.publishableKey; + if (publishableKey) return { publishableKey, omsProjectId: data.omsProjectId }; + } catch { + // ignore malformed config + } + } + return { publishableKey: DEFAULT_OMS_PUBLISHABLE_KEY, omsProjectId: envProj }; +} + +/** Populate OMS env vars from builder.json at startup. */ +export function bootstrapOmsConfig(): void { + const cfg = loadOmsConfig(); + if (!process.env.OMS_PUBLISHABLE_KEY) process.env.OMS_PUBLISHABLE_KEY = cfg.publishableKey; + if (!process.env.SEQUENCE_OMS_PROJECT_ID && cfg.omsProjectId) + process.env.SEQUENCE_OMS_PROJECT_ID = cfg.omsProjectId; + + // Also bootstrap the OMS project access key (used by Trails swap/bridge + // and the indexer) from builder.json into the env, if present — env always + // wins. This is separate from the OMS wallet credentials above. + if (!process.env.SEQUENCE_PROJECT_ACCESS_KEY) { + const configPath = path.join(STORAGE_DIR, 'builder.json'); + if (fs.existsSync(configPath)) { + try { + const data = JSON.parse(fs.readFileSync(configPath, 'utf8')); + if (data.accessKey) process.env.SEQUENCE_PROJECT_ACCESS_KEY = data.accessKey as string; + } catch { + // ignore malformed config + } + } + } +} + +export async function saveOmsWalletPointer(name: string, pointer: OmsWalletPointer): Promise { + ensureStorageDir(); + const walletPath = path.join(STORAGE_DIR, 'wallets', `${name}.json`); + fs.writeFileSync(walletPath, JSON.stringify(pointer, null, 2), { mode: 0o600 }); +} + +export async function loadOmsWalletPointer(name: string): Promise { + const walletPath = path.join(STORAGE_DIR, 'wallets', `${name}.json`); + if (!fs.existsSync(walletPath)) return null; + try { + const data = JSON.parse(fs.readFileSync(walletPath, 'utf8')); + // Accept any pointer with an address (loginMethod is display-only; legacy + // pre-browser sessions still load until they expire). + if (data.walletAddress && typeof data.loginMethod === 'string') return data as OmsWalletPointer; + } catch { + // not a valid OMS pointer file + } + return null; +} + +/** Remove an OMS wallet's pointer + the SDK's per-wallet state dir. */ +export async function deleteOmsWallet(name: string): Promise { + const walletPath = path.join(STORAGE_DIR, 'wallets', `${name}.json`); + if (fs.existsSync(walletPath)) fs.unlinkSync(walletPath); + const dir = path.join(STORAGE_DIR, 'oms', name); + if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true, force: true }); } diff --git a/packages/polygon-agent-cli/src/lib/tx-dispatch.ts b/packages/polygon-agent-cli/src/lib/tx-dispatch.ts new file mode 100644 index 0000000..e1ac8e6 --- /dev/null +++ b/packages/polygon-agent-cli/src/lib/tx-dispatch.ts @@ -0,0 +1,15 @@ +// Transaction dispatch — submits via the OMS V3 primitive. +// +// Command call sites import `runTx` from here. (Kept as a thin indirection so +// call sites don't import oms-tx directly, leaving room for future routing.) + +import type { OmsTxParams, OmsTxResult } from './oms-tx.ts'; + +import { runOmsTx } from './oms-tx.ts'; + +export type RunTxParams = OmsTxParams; +export type RunTxResult = OmsTxResult; + +export async function runTx(params: RunTxParams): Promise { + return runOmsTx(params); +} diff --git a/packages/polygon-agent-cli/src/lib/utils.ts b/packages/polygon-agent-cli/src/lib/utils.ts index bf4c936..9d78027 100644 --- a/packages/polygon-agent-cli/src/lib/utils.ts +++ b/packages/polygon-agent-cli/src/lib/utils.ts @@ -79,12 +79,36 @@ export function getIndexerUrl(): string { ); } -/** Get RPC URL for a network via Sequence nodes */ +/** Get RPC URL for a network via OMS nodes */ export function getRpcUrl(network: NetworkMetadata): string { const accessKey = process.env.SEQUENCE_PROJECT_ACCESS_KEY || ''; return `https://nodes.sequence.app/${network.name}/${accessKey}`; } +// Public RPC fallbacks per chain — used for read-only calls (e.g. tx receipt +// polling) when no OMS project access key is available (the OMS path uses +// publishableKey/projectId, not a nodes.sequence.app access key). +const PUBLIC_RPC_BY_CHAIN_ID: Record = { + 137: 'https://polygon-rpc.com', + 80002: 'https://rpc-amoy.polygon.technology', + 8453: 'https://mainnet.base.org', + 84532: 'https://sepolia.base.org', + 1: 'https://eth.llamarpc.com', + 42161: 'https://arb1.arbitrum.io/rpc', + 10: 'https://mainnet.optimism.io' +}; + +/** + * Read-only RPC URL. Prefers the OMS nodes endpoint when a project access + * key is configured; otherwise falls back to a public RPC for the chain. Safe + * for both the legacy (dapp-client) and OMS (typescript-sdk) paths. + */ +export function getReadRpcUrl(network: NetworkMetadata): string { + const accessKey = process.env.SEQUENCE_PROJECT_ACCESS_KEY; + if (accessKey) return `https://nodes.sequence.app/${network.name}/${accessKey}`; + return PUBLIC_RPC_BY_CHAIN_ID[network.chainId] || `https://polygon-rpc.com`; +} + /** Explorer URL for transaction */ export function getExplorerUrl(network: NetworkMetadata, txHash: string): string { const raw = network.blockExplorer?.rootUrl || `https://polygonscan.com`; diff --git a/packages/polygon-agent-cli/src/types.d.ts b/packages/polygon-agent-cli/src/types.d.ts index a6f787d..b2f1690 100644 --- a/packages/polygon-agent-cli/src/types.d.ts +++ b/packages/polygon-agent-cli/src/types.d.ts @@ -1,13 +1,2 @@ // Ambient declarations for untyped dependencies - -declare module 'tweetnacl-sealedbox-js' { - export function open( - ciphertext: Uint8Array, - publicKey: Uint8Array, - secretKey: Uint8Array - ): Uint8Array | null; - - export function seal(message: Uint8Array, publicKey: Uint8Array): Uint8Array; - - export function overheadLength(): number; -} +export {}; diff --git a/packages/polygon-agent-cli/tsconfig.json b/packages/polygon-agent-cli/tsconfig.json index 1f18d4d..9e53e3d 100644 --- a/packages/polygon-agent-cli/tsconfig.json +++ b/packages/polygon-agent-cli/tsconfig.json @@ -4,5 +4,5 @@ "jsx": "react-jsx", "jsxImportSource": "react" }, - "include": ["src/**/*.ts", "src/**/*.tsx"] + "include": ["src/**/*.ts", "src/**/*.tsx", "vitest.config.ts"] } diff --git a/packages/polygon-agent-cli/vitest.config.ts b/packages/polygon-agent-cli/vitest.config.ts new file mode 100644 index 0000000..357f4ff --- /dev/null +++ b/packages/polygon-agent-cli/vitest.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from 'vitest/config'; + +// The repo tsconfig targets es2024 (Node 24+ dev requirement), but the +// esbuild bundled with this Vite/Vitest major doesn't recognize that target +// string yet and warns on every transform. Vite's esbuild plugin loads the +// project tsconfig's `target` into `tsconfigRaw.compilerOptions.target` +// regardless of the top-level `esbuild.target` below, so both need the +// override to actually silence the warning; other tsconfig-derived options +// (jsx, verbatimModuleSyntax, etc.) are untouched. Tests still run on +// Node >=20 either way, so lowering the transform target has no effect on +// behavior. +export default defineConfig({ + esbuild: { + target: 'es2023', + tsconfigRaw: { compilerOptions: { target: 'es2023' } } + } +}); diff --git a/packages/shared/CHANGELOG.md b/packages/shared/CHANGELOG.md deleted file mode 100644 index 42c551e..0000000 --- a/packages/shared/CHANGELOG.md +++ /dev/null @@ -1,195 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [0.1.15](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.14...@polygonlabs/agent-shared@0.1.15) (2026-06-09) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.14](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.13...@polygonlabs/agent-shared@0.1.14) (2026-05-27) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.13](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.12...@polygonlabs/agent-shared@0.1.13) (2026-04-30) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.12](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.11...@polygonlabs/agent-shared@0.1.12) (2026-04-29) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.11](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.10...@polygonlabs/agent-shared@0.1.11) (2026-04-29) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.10](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.9...@polygonlabs/agent-shared@0.1.10) (2026-04-28) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.9](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.8...@polygonlabs/agent-shared@0.1.9) (2026-04-27) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.8](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.7...@polygonlabs/agent-shared@0.1.8) (2026-04-27) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.7](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.6...@polygonlabs/agent-shared@0.1.7) (2026-04-22) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.6](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.5...@polygonlabs/agent-shared@0.1.6) (2026-04-22) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.5](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.4...@polygonlabs/agent-shared@0.1.5) (2026-04-21) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.4](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.3...@polygonlabs/agent-shared@0.1.4) (2026-04-21) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.3](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.2...@polygonlabs/agent-shared@0.1.3) (2026-04-16) - -**Note:** Version bump only for package @polygonlabs/agent-shared - - - - - -## [0.1.2](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.1.1...@polygonlabs/agent-shared@0.1.2) (2026-04-14) - - -### Bug Fixes - -* **cli:** bundle agent-shared into CLI instead of publishing to npm ([1cc2d7b](https://github.com/0xPolygon/polygon-agent-cli/commit/1cc2d7b28b971f7b4b85d9473393c9fce92edd57)) - - - - - -## [0.1.1](https://github.com/0xPolygon/polygon-agent-cli/compare/@polygonlabs/agent-shared@0.5.0...@polygonlabs/agent-shared@0.1.1) (2026-04-14) - - -### Bug Fixes - -* **shared:** publish agent-shared to npm so agent-cli installs correctly ([a757cba](https://github.com/0xPolygon/polygon-agent-cli/commit/a757cba418556eb6d59963bcedf9af1a65590aea)) -* **shared:** use publishConfig so workspace typecheck resolves src, npm gets dist ([be8ec61](https://github.com/0xPolygon/polygon-agent-cli/commit/be8ec616b501c4fa756b3c72e61b1febf3a0a474)) - - - - - -# 0.5.0 (2026-04-14) - - -### Bug Fixes - -* **connector-ui:** preserve implicit session metadata, remove tweetnacl, add rid validation ([ca4c4aa](https://github.com/0xPolygon/polygon-agent-cli/commit/ca4c4aa7ce972639e80b3fe4c8cc6abd01db3df1)) -* **shared:** correct import path in plan, suppress vitest warning, add requestId guard ([84d5673](https://github.com/0xPolygon/polygon-agent-cli/commit/84d56731a17ddd6a40534c6cc97ae2e8e43d6ff4)) - - -### Features - -* **shared:** add v2 crypto protocol package (X25519+HKDF+XChaCha20) ([a5c23b3](https://github.com/0xPolygon/polygon-agent-cli/commit/a5c23b3b63ea464ea514734bcd9aa36895480701)) - - - - - -# 0.4.0 (2026-04-14) - - -### Bug Fixes - -* **connector-ui:** preserve implicit session metadata, remove tweetnacl, add rid validation ([ca4c4aa](https://github.com/0xPolygon/polygon-agent-cli/commit/ca4c4aa7ce972639e80b3fe4c8cc6abd01db3df1)) -* **shared:** correct import path in plan, suppress vitest warning, add requestId guard ([84d5673](https://github.com/0xPolygon/polygon-agent-cli/commit/84d56731a17ddd6a40534c6cc97ae2e8e43d6ff4)) - - -### Features - -* **shared:** add v2 crypto protocol package (X25519+HKDF+XChaCha20) ([a5c23b3](https://github.com/0xPolygon/polygon-agent-cli/commit/a5c23b3b63ea464ea514734bcd9aa36895480701)) - - - - - -# 0.3.0 (2026-04-14) - - -### Bug Fixes - -* **connector-ui:** preserve implicit session metadata, remove tweetnacl, add rid validation ([ca4c4aa](https://github.com/0xPolygon/polygon-agent-cli/commit/ca4c4aa7ce972639e80b3fe4c8cc6abd01db3df1)) -* **shared:** correct import path in plan, suppress vitest warning, add requestId guard ([84d5673](https://github.com/0xPolygon/polygon-agent-cli/commit/84d56731a17ddd6a40534c6cc97ae2e8e43d6ff4)) - - -### Features - -* **shared:** add v2 crypto protocol package (X25519+HKDF+XChaCha20) ([a5c23b3](https://github.com/0xPolygon/polygon-agent-cli/commit/a5c23b3b63ea464ea514734bcd9aa36895480701)) - - - - - -# 0.2.0 (2026-04-14) - - -### Bug Fixes - -* **connector-ui:** preserve implicit session metadata, remove tweetnacl, add rid validation ([ca4c4aa](https://github.com/0xPolygon/polygon-agent-cli/commit/ca4c4aa7ce972639e80b3fe4c8cc6abd01db3df1)) -* **shared:** correct import path in plan, suppress vitest warning, add requestId guard ([84d5673](https://github.com/0xPolygon/polygon-agent-cli/commit/84d56731a17ddd6a40534c6cc97ae2e8e43d6ff4)) - - -### Features - -* **shared:** add v2 crypto protocol package (X25519+HKDF+XChaCha20) ([a5c23b3](https://github.com/0xPolygon/polygon-agent-cli/commit/a5c23b3b63ea464ea514734bcd9aa36895480701)) diff --git a/packages/shared/crypto.test.ts b/packages/shared/crypto.test.ts deleted file mode 100644 index 1604ba1..0000000 --- a/packages/shared/crypto.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { describe, it, expect } from 'vitest'; - -import type { SessionPayload } from './src/types.js'; - -import { - generateX25519Keypair, - encryptSession, - decryptSession, - generateCode, - computeCodeHash -} from './src/crypto.js'; -import { bytesToHex } from './src/encoding.js'; - -const SAMPLE_PAYLOAD: SessionPayload = { - version: 1, - wallet_address: '0xc448e20a23d9ca5b0f9d667c6676f64c73cff8b7', - chain_id: 137, - session_private_key: '0x' + 'ab'.repeat(32), - session_address: '0x' + 'cd'.repeat(20), - permissions: { native_limit: '2000000000000000000', erc20_limits: [] }, - expiry: Math.floor(Date.now() / 1000) + 86400 * 183, - ecosystem_wallet_url: 'https://wallet.sequence.app', - dapp_origin: 'https://agentconnect.polygon.technology', - project_access_key: 'AQAAAAAAAAAAAAAAAAAAAAAAAAAtest' -}; - -describe('session encrypt/decrypt round-trip', () => { - it('decrypts to original payload', () => { - const { secretKey: cliSk, publicKey: cliPk } = generateX25519Keypair(); - const requestId = 'abc12345'; - const cliPkHex = bytesToHex(cliPk); - - const { encrypted, code } = encryptSession(SAMPLE_PAYLOAD, cliPkHex, requestId); - - expect(code).toMatch(/^\d{6}$/); - expect(encrypted.wallet_pk_hex).toHaveLength(64); - expect(encrypted.nonce_hex).toHaveLength(48); - - const decrypted = decryptSession(encrypted, cliSk, code, requestId); - expect(decrypted.wallet_address).toBe(SAMPLE_PAYLOAD.wallet_address); - expect(decrypted.chain_id).toBe(137); - expect(decrypted.session_private_key).toBe(SAMPLE_PAYLOAD.session_private_key); - }); - - it('throws on wrong code', () => { - const { secretKey: cliSk, publicKey: cliPk } = generateX25519Keypair(); - const requestId = 'abc12345'; - const { encrypted } = encryptSession(SAMPLE_PAYLOAD, bytesToHex(cliPk), requestId); - expect(() => decryptSession(encrypted, cliSk, '000000', requestId)).toThrow(); - }); - - it('generates 6-digit codes', () => { - for (let i = 0; i < 20; i++) { - const code = generateCode(); - expect(code).toMatch(/^\d{6}$/); - expect(parseInt(code)).toBeGreaterThanOrEqual(0); - expect(parseInt(code)).toBeLessThan(1_000_000); - } - }); - - it('computeCodeHash is deterministic', () => { - const h1 = computeCodeHash('req123', '847291'); - const h2 = computeCodeHash('req123', '847291'); - expect(bytesToHex(h1)).toBe(bytesToHex(h2)); - }); -}); diff --git a/packages/shared/eslint.config.js b/packages/shared/eslint.config.js deleted file mode 100644 index 82fdc54..0000000 --- a/packages/shared/eslint.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from 'eslint/config'; - -import { recommended, typescript } from '@polygonlabs/apps-team-lint'; - -export default defineConfig([ - ...recommended({ globals: 'node' }), - ...typescript({ tsconfigRootDir: import.meta.dirname }) -]); diff --git a/packages/shared/package.json b/packages/shared/package.json deleted file mode 100644 index dba8525..0000000 --- a/packages/shared/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@polygonlabs/agent-shared", - "version": "0.1.15", - "private": true, - "type": "module", - "main": "./src/index.ts", - "exports": { - ".": "./src/index.ts" - }, - "scripts": { - "lint": "eslint .", - "typecheck": "tsc --noEmit", - "test": "vitest run", - "clean": "rm -rf node_modules *.tsbuildinfo" - }, - "dependencies": { - "@noble/ciphers": "^1.2.1", - "@noble/curves": "^1.8.1", - "@noble/hashes": "^1.7.2" - }, - "devDependencies": { - "vitest": "3.1.4" - } -} diff --git a/packages/shared/src/constants.ts b/packages/shared/src/constants.ts deleted file mode 100644 index e1b25a1..0000000 --- a/packages/shared/src/constants.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const PROTOCOL_VERSION = 'polygon-agent-session-v1'; -export const CODE_LENGTH = 6; -export const MAX_CODE_ATTEMPTS = 3; -export const REQUEST_TTL_SECONDS = 300; -export const REQUEST_ID_LENGTH = 8; diff --git a/packages/shared/src/crypto.ts b/packages/shared/src/crypto.ts deleted file mode 100644 index 5033329..0000000 --- a/packages/shared/src/crypto.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { xchacha20poly1305 } from '@noble/ciphers/chacha'; -import { x25519 } from '@noble/curves/ed25519'; -import { hkdf } from '@noble/hashes/hkdf'; -import { sha256 } from '@noble/hashes/sha2'; -import { randomBytes } from '@noble/hashes/utils'; - -import type { EncryptedPayload, SessionPayload } from './types.js'; - -import { PROTOCOL_VERSION, CODE_LENGTH } from './constants.js'; -import { bytesToHex, hexToBytes, b64urlEncode, b64urlDecode } from './encoding.js'; - -export interface X25519Keypair { - secretKey: Uint8Array; - publicKey: Uint8Array; -} - -export function generateX25519Keypair(): X25519Keypair { - const secretKey = randomBytes(32); - const publicKey = x25519.getPublicKey(secretKey); - return { secretKey, publicKey }; -} - -/** Generates a random 6-digit code string, zero-padded. */ -export function generateCode(): string { - // Use 4 random bytes, take mod 1_000_000 to get 0–999999 - const bytes = randomBytes(4); - const n = new DataView(bytes.buffer).getUint32(0) % 1_000_000; - return n.toString().padStart(CODE_LENGTH, '0'); -} - -/** SHA-256(requestId + code). Used as the code_hash sent to the relay. */ -export function computeCodeHash(requestId: string, code: string): Uint8Array { - if (!requestId) throw new Error('requestId must not be empty'); - return sha256(new TextEncoder().encode(requestId + code)); -} - -function deriveEncKey( - shared: Uint8Array, - code: string, - cliPkHex: string, - walletPkHex: string -): Uint8Array { - const salt = sha256(new TextEncoder().encode(code)); - const info = new TextEncoder().encode(cliPkHex + walletPkHex + PROTOCOL_VERSION); - return hkdf(sha256, shared, salt, info, 32); -} - -/** - * Encrypt a SessionPayload for the CLI to decrypt. - * Returns the EncryptedPayload (to POST to relay) and the plaintext code (to display to user). - */ -export function encryptSession( - payload: SessionPayload, - cliPkHex: string, - requestId: string -): { encrypted: EncryptedPayload; code: string } { - const cliPk = hexToBytes(cliPkHex); - const { secretKey: walletSk, publicKey: walletPk } = generateX25519Keypair(); - const shared = x25519.getSharedSecret(walletSk, cliPk); - - const walletPkHex = bytesToHex(walletPk); - const code = generateCode(); - const encKey = deriveEncKey(shared, code, cliPkHex, walletPkHex); - - const nonce = randomBytes(24); - const aad = new Uint8Array([...cliPk, ...walletPk]); - const plaintext = new TextEncoder().encode(JSON.stringify(payload)); - - const cipher = xchacha20poly1305(encKey, nonce, aad); - const ciphertext = cipher.encrypt(plaintext); - - const encrypted: EncryptedPayload = { - wallet_pk_hex: walletPkHex, - nonce_hex: bytesToHex(nonce), - ciphertext_b64url: b64urlEncode(ciphertext), - code_hash_hex: bytesToHex(computeCodeHash(requestId, code)) - }; - - return { encrypted, code }; -} - -/** - * Decrypt a session payload received from the relay. - * The code is provided by the user out-of-band. - */ -export function decryptSession( - encrypted: EncryptedPayload, - cliSk: Uint8Array, - code: string, - requestId: string -): SessionPayload { - if (!requestId) throw new Error('requestId must not be empty'); - const cliPk = x25519.getPublicKey(cliSk); - const walletPk = hexToBytes(encrypted.wallet_pk_hex); - const shared = x25519.getSharedSecret(cliSk, walletPk); - - const cliPkHex = bytesToHex(cliPk); - const walletPkHex = encrypted.wallet_pk_hex; - const encKey = deriveEncKey(shared, code, cliPkHex, walletPkHex); - - const nonce = hexToBytes(encrypted.nonce_hex); - const aad = new Uint8Array([...cliPk, ...walletPk]); - const ciphertext = b64urlDecode(encrypted.ciphertext_b64url); - - // Verify the code hash before attempting decryption - const expectedHash = bytesToHex(computeCodeHash(requestId, code)); - if (expectedHash !== encrypted.code_hash_hex) { - throw new Error('Invalid code: hash mismatch'); - } - - const cipher = xchacha20poly1305(encKey, nonce, aad); - // xchacha20poly1305.decrypt throws if auth tag fails - const plaintext = cipher.decrypt(ciphertext); - return JSON.parse(new TextDecoder().decode(plaintext)) as SessionPayload; -} diff --git a/packages/shared/src/encoding.ts b/packages/shared/src/encoding.ts deleted file mode 100644 index 0c14608..0000000 --- a/packages/shared/src/encoding.ts +++ /dev/null @@ -1,30 +0,0 @@ -export function bytesToHex(bytes: Uint8Array): string { - return Array.from(bytes) - .map((b) => b.toString(16).padStart(2, '0')) - .join(''); -} - -export function hexToBytes(hex: string): Uint8Array { - if (hex.length % 2 !== 0) throw new Error('Invalid hex string'); - const bytes = new Uint8Array(hex.length / 2); - for (let i = 0; i < bytes.length; i++) { - bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); - } - return bytes; -} - -export function b64urlEncode(bytes: Uint8Array): string { - // Works in Node.js and Cloudflare Workers - let bin = ''; - for (const b of bytes) bin += String.fromCharCode(b); - return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); -} - -export function b64urlDecode(str: string): Uint8Array { - const norm = str.replace(/-/g, '+').replace(/_/g, '/'); - const pad = norm.length % 4 === 0 ? '' : '='.repeat(4 - (norm.length % 4)); - const bin = atob(norm + pad); - const bytes = new Uint8Array(bin.length); - for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i); - return bytes; -} diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts deleted file mode 100644 index e401f35..0000000 --- a/packages/shared/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './constants.js'; -export * from './types.js'; -export * from './encoding.js'; -export * from './crypto.js'; diff --git a/packages/shared/src/types.ts b/packages/shared/src/types.ts deleted file mode 100644 index bcc94b7..0000000 --- a/packages/shared/src/types.ts +++ /dev/null @@ -1,51 +0,0 @@ -export interface ImplicitSession { - pk: string; - attestation: string; - identity_sig: string; - /** Optional fields preserved for Sequence wallet path compatibility */ - guard?: string; - login_method?: string; - user_email?: string; -} - -export interface SessionPermissions { - /** Max native token spend, as wei string */ - native_limit?: string; - erc20_limits?: Array<{ token_address: string; limit: string }>; - contract_calls?: Array<{ address: string; functions: string[] }>; -} - -export interface SessionPayload { - version: 1; - wallet_address: string; - chain_id: number; - /** Hex-encoded explicit session private key */ - session_private_key: string; - /** Explicit session signer address */ - session_address: string; - permissions: SessionPermissions; - /** Unix timestamp — expiry of explicit session */ - expiry: number; - ecosystem_wallet_url: string; - dapp_origin: string; - project_access_key: string; - relayer_url?: string; - /** Full explicit session config, JSON-stringified (for dapp-client reconstruction) */ - session_config?: string; - implicit_session?: ImplicitSession; -} - -export interface EncryptedPayload { - wallet_pk_hex: string; - nonce_hex: string; - ciphertext_b64url: string; - code_hash_hex: string; -} - -export interface RelayCreateResponse { - request_id: string; -} - -export interface RelayStatusResponse { - status: 'pending' | 'ready'; -} diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json deleted file mode 100644 index 56a361a..0000000 --- a/packages/shared/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { "target": "ES2022" }, - "include": ["src/**/*.ts", "crypto.test.ts", "vitest.config.ts"] -} diff --git a/packages/shared/vitest.config.ts b/packages/shared/vitest.config.ts deleted file mode 100644 index ed58c0d..0000000 --- a/packages/shared/vitest.config.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { defineConfig } from 'vitest/config'; -export default defineConfig({ - test: { environment: 'node' }, - esbuild: { target: 'es2022' } -}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2728922..a8e9493 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,7 +23,7 @@ importers: version: 20.4.2 '@polygonlabs/apps-team-lint': specifier: ^2.0.0 - version: 2.0.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + version: 2.0.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3))(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) '@tsconfig/node-ts': specifier: ^23.6.4 version: 23.6.4 @@ -38,7 +38,7 @@ importers: version: 9.2.1 eslint: specifier: ^10.0.0 - version: 10.0.3(jiti@2.6.1) + version: 10.0.3(jiti@2.7.0) husky: specifier: ^9.1.7 version: 9.1.7 @@ -55,45 +55,33 @@ importers: specifier: ^5.8.3 version: 5.9.3 - packages/connector-ui: + packages/agentconnect-ui: dependencies: 0xtrails: specifier: ^0.14.0 - version: 0.14.0(88585348c7fe3646803356f2c1f98627) - '@0xsequence/dapp-client': - specifier: 3.0.0-beta.16 - version: 3.0.0-beta.16(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + version: 0.14.0(0xsequence@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@0xsequence/api@3.0.12)(@0xsequence/network@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@react-oauth/google@0.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(bs58@6.0.0)(bufferutil@4.1.0)(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-apple-signin-auth@1.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) '@0xsequence/wallet-primitives': specifier: 3.0.0-beta.16 version: 3.0.0-beta.16(typescript@5.9.3)(zod@3.25.76) - '@polygonlabs/agent-shared': - specifier: workspace:* - version: link:../shared - '@tailwindcss/vite': - specifier: ^4.1.18 - version: 4.2.1(vite@5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1)) lucide-react: specifier: ^0.564.0 version: 0.564.0(react@18.3.1) - ox: - specifier: ^0.11.3 - version: 0.11.3(typescript@5.9.3)(zod@3.25.76) react: specifier: ^18.3.1 version: 18.3.1 react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) - serve: - specifier: ^14.2.4 - version: 14.2.5 tailwindcss: specifier: ^4 - version: 4.2.1 + version: 4.3.2 devDependencies: '@cloudflare/workers-types': - specifier: ^4.20260317.1 + specifier: ^4 version: 4.20260317.1 + '@tailwindcss/vite': + specifier: ^4.1.18 + version: 4.3.2(vite@5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1)) '@types/react': specifier: ^18.3.3 version: 18.3.28 @@ -102,61 +90,40 @@ importers: version: 18.3.7(@types/react@18.3.28) '@vitejs/plugin-react': specifier: ^4.3.1 - version: 4.7.0(vite@5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1)) + version: 4.7.0(vite@5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1)) + typescript: + specifier: ^5 + version: 5.9.3 vite: specifier: ^5.4.0 - version: 5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1) - wrangler: - specifier: ^4.67.0 - version: 4.69.0(@cloudflare/workers-types@4.20260317.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6) + version: 5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) + vitest: + specifier: ^3.0.0 + version: 3.2.7(@types/debug@4.1.13)(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) + + packages/oidc-relay: + devDependencies: + '@cloudflare/workers-types': + specifier: ^4.20240712.0 + version: 4.20260317.1 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vitest: + specifier: ^3.0.0 + version: 3.2.7(@types/debug@4.1.13)(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) packages/polygon-agent-cli: dependencies: - '@0xsequence/abi': - specifier: 3.0.0-beta.17 - version: 3.0.0-beta.17 - '@0xsequence/api': - specifier: 3.0.0-beta.17 - version: 3.0.0-beta.17 - '@0xsequence/builder': - specifier: 3.0.0-beta.17 - version: 3.0.0-beta.17 - '@0xsequence/dapp-client': - specifier: 3.0.0-beta.17 - version: 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - '@0xsequence/dapp-client-cli': - specifier: 0.1.5 - version: 0.1.5(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - '@0xsequence/indexer': - specifier: ^2.3.40 - version: 2.3.41 '@0xsequence/network': specifier: ^2.3.40 version: 2.3.41(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/relayer': - specifier: 3.0.0-beta.17 - version: 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - '@0xsequence/wallet-core': - specifier: 3.0.0-beta.17 - version: 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - '@0xsequence/wallet-primitives': - specifier: 3.0.0-beta.17 - version: 3.0.0-beta.17(typescript@5.9.3)(zod@4.3.6) - '@0xsequence/wallet-wdk': - specifier: 3.0.0-beta.17 - version: 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) '@0xtrails/api': specifier: ^0.10.4 version: 0.10.4 - '@noble/ciphers': - specifier: ^1.2.1 - version: 1.3.0 - '@noble/curves': - specifier: 1.9.7 - version: 1.9.7 - '@noble/hashes': - specifier: 1.8.0 - version: 1.8.0 + '@polygonlabs/oms-wallet': + specifier: 0.2.0 + version: 0.2.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) '@polymarket/clob-client-v2': specifier: ^1.0.0 version: 1.0.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) @@ -193,22 +160,13 @@ importers: react: specifier: ^18.3.1 version: 18.3.1 - tweetnacl: - specifier: ^1.0.3 - version: 1.0.3 - tweetnacl-sealedbox-js: - specifier: ^1.2.0 - version: 1.2.0 viem: - specifier: ^2.45.3 - version: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) + specifier: ^2.48.4 + version: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) yargs: specifier: ^17.7.2 version: 17.7.2 devDependencies: - '@polygonlabs/agent-shared': - specifier: workspace:* - version: link:../shared '@types/react': specifier: ^18.3.1 version: 18.3.28 @@ -218,27 +176,14 @@ importers: esbuild: specifier: ^0.28.0 version: 0.28.0 - - packages/shared: - dependencies: - '@noble/ciphers': - specifier: ^1.2.1 - version: 1.3.0 - '@noble/curves': - specifier: 1.9.7 - version: 1.9.7 - '@noble/hashes': - specifier: 1.8.0 - version: 1.8.0 - devDependencies: vitest: - specifier: 3.1.4 - version: 3.1.4(@types/debug@4.1.13)(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1) + specifier: ^3.0.0 + version: 3.2.7(@types/debug@4.1.13)(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) packages: - 0xsequence@2.3.43: - resolution: {integrity: sha512-lf/IPtqNqRmeWJOUVxUHIAVCt+wvgYsJ6P/8pA7RrWBqdnzTLnvrJlEMspB3P+jzFOfzAndGBKe4KKNVMH+F7A==} + 0xsequence@2.3.44: + resolution: {integrity: sha512-MzX9a4BiFQsGapEDKqp6dFHblSfyXPKnD90s7zkKIQjWm6D9KZ5PTO/77mdCFjhQitVeTkXbq8bPRjwXBddKtA==} peerDependencies: ethers: '>=6' @@ -254,31 +199,25 @@ packages: '@0xsequence/abi@2.3.41': resolution: {integrity: sha512-CMiuW/5HiNxB0jpVBEUZfVkwXgeiT9HbsUy/7FL/8XWv9rLM5mE9Y6fj4QAH/jaRnvGfG4iDcCbq05+PQ/q5Rw==} - '@0xsequence/abi@2.3.43': - resolution: {integrity: sha512-ybWRT+knMPpOH/XBucw8/BviyqomLAgvbCxFTNB0WAaO3inVCdHEil2keBFXgPKGlEVozQ5ZhE0k6WQxb3bZSw==} - - '@0xsequence/abi@3.0.0-beta.17': - resolution: {integrity: sha512-YoIBLe1CzhEX0fLAWgI8ccPKT9EptzGsCjXPlZWyEB6lRyxvM3qhtVoZfB5t2I4n7IIhgS6FN8KdjFBidnhOkw==} + '@0xsequence/abi@2.3.44': + resolution: {integrity: sha512-/rRv9mmCpDQH4qGBa6cUBcl3CTKVpLetqIUMVX/mei40SdR/nUcg1eCuRtkcVIEc8mgJ+Pz+LBe2EzAqeUAivA==} - '@0xsequence/account@2.3.43': - resolution: {integrity: sha512-MVAZcUPSnpUuXu9NaZN2VGv8/oIFjhuYbVKx2grBiGA8oAxtkOYiV5If2xmpnRAvl1W/f4cAl4oJi6q0bLUfkA==} + '@0xsequence/account@2.3.44': + resolution: {integrity: sha512-kj7RlMQSFMMUcK/vzHS6XRIolkeb03YRAnq4ypyymL77PcXt6k3PsvjejgwB9H8UYpPN2MRVKJkvK+FC2bHbNw==} peerDependencies: ethers: '>=6' - '@0xsequence/api@2.3.43': - resolution: {integrity: sha512-1L6oNcstgG1+P7Jxo4fwY/uqT5C6iAZXKJc6DZKdsJiEn3BUZ+Cyx9j2sMMoqQ8hx18x9wrn8368T/dmJ8Rhqg==} + '@0xsequence/api@2.3.44': + resolution: {integrity: sha512-Ifg0Bzk/sK+Rvcc2OWcu8PyE/ksC+SuKJxLzPs3JKVkOfKZ1TMlFOvp+J4rdUL5xNuNVrO1xe99s/jABdpxoUg==} - '@0xsequence/api@3.0.0-beta.17': - resolution: {integrity: sha512-vvw+fzSZNmRtA6MTYNDKrtNjGl3u0aaEJviLkJ3oUruecKUuIPJkLmgvA8kNQQq0XJT8D9SVO8UJQYSipSkJHA==} + '@0xsequence/api@3.0.12': + resolution: {integrity: sha512-1hLNDh4BFbjFgdfNtnpQGLZMj9+aTDyJEmDHtxnNsuyEKhkpG7AVy6iXmr+s0BjvT3kYk545QwxPURshlTm13A==} - '@0xsequence/auth@2.3.43': - resolution: {integrity: sha512-qtm7WvQ5+5wckBBqPa7mDbWtgm0wDHvCzIEaieS1de3a+xZETx/TvRguYL62Y0HXKtnhtV+BkUxiuhFteNfpiQ==} + '@0xsequence/auth@2.3.44': + resolution: {integrity: sha512-Vcln/2NzgS8Gr++SOkUwmWXEx0y4KE5NSbayva36l97LMnM27xMuu76nH6mzbyxHg3yu7sfDZ5iHRy5O3HGXrA==} peerDependencies: ethers: '>=6' - '@0xsequence/builder@3.0.0-beta.17': - resolution: {integrity: sha512-Oy4KAO4ow5AnTfHMJndZBG9ZF0MCSpih3NuYD1BzkPlueYMckWc6MKJNO+/vJn5ioKZUkeCGafOfT3WwbsrQpg==} - '@0xsequence/connect@5.4.8': resolution: {integrity: sha512-Hv+fLQ3Ets2319bSnMMhBbWsFdXXjkl5tmYwC1gbrOUju84yvqhC3eIrDdA1F6VaQFaf9Ttxu1yROeCKuzZLrw==} peerDependencies: @@ -299,21 +238,11 @@ packages: peerDependencies: ethers: '>=6' - '@0xsequence/core@2.3.43': - resolution: {integrity: sha512-kPJs8SS35fIYS0wrNJ/2ODW3YyBWKdEXq4mncyG4CvCO7zT6kohsYljC3uUyH4NwWGCYoMt1T8c1CKwnZBpJTQ==} + '@0xsequence/core@2.3.44': + resolution: {integrity: sha512-MYJoSZ0057Kseb+q4WaHNwWYOoVSaf7LnHOoq5OS525jiHj7zYl9mVIveooG0MrEcSe6q+FRu0AWEa7c5KbA4g==} peerDependencies: ethers: '>=6' - '@0xsequence/dapp-client-cli@0.1.5': - resolution: {integrity: sha512-9vQsypf9mNUCOEb4oKfQW+7gmP5N2Tunf0Bm1dSY9FTPTqcvNHE/6vYFKgigVxYg5/favHxIiB8a61dqo1O1ew==} - hasBin: true - - '@0xsequence/dapp-client@3.0.0-beta.16': - resolution: {integrity: sha512-lo3ZNncrirvZEVpiUUfts/Skp6kmqJlKxUpEHj/1n+LO/L53dyqMUx9ti2qMIJGkAyKzZ66NdiqYqJoRKNNBIw==} - - '@0xsequence/dapp-client@3.0.0-beta.17': - resolution: {integrity: sha512-Nb3ym/T1SNuyu6Y4cHBkPiZkNrFYyKEnl8CRpllmEJDnfAYAaGTvOhmeCqESDYLVNJe976UgxhQnkhxn5IpqNA==} - '@0xsequence/design-system@2.1.11': resolution: {integrity: sha512-wfuY9v2dNQxw9qAYyflwcKzuiiVqm4qqn2Jkoyw/CqxODcqQ3orUsGxjnbyvCWOwvHbH908c4LOZj/TBI6T0Fw==} peerDependencies: @@ -326,49 +255,39 @@ packages: peerDependencies: ethers: '>=6' - '@0xsequence/guard@2.3.43': - resolution: {integrity: sha512-gVyCzjId93iTGBJTCarHeu5aVcvQKNa7PslYc33PPfLpXTUgOZRGA4ClifiEP5A0oTg+y73hxawmZiv3JTUhXw==} + '@0xsequence/guard@2.3.44': + resolution: {integrity: sha512-3AkPXIyour4orjZNrcAbDBE/YywP2qVLVqA8uBsc6gSa3htGE21sCvT1smCDxiSM0eSIPdz1ozwdj58vdUR4vA==} peerDependencies: ethers: '>=6' - '@0xsequence/guard@3.0.0': - resolution: {integrity: sha512-3GAC7LM/o8nesW60UmqUPfY7DFNXFKzJ8rCEbkWwpC7ugycbtHNTWJUCDnQzVqVW8TXHKOFhHyxYpLQ0w8xJLQ==} - - '@0xsequence/guard@3.0.0-beta.19': - resolution: {integrity: sha512-4A+LjH+uCywX9JD+O76D6o2ZkoIvym7LEVo5bxAcRV8zFyuwy7yiQHdiVvNcNaGayApn0Y7vt6mfZKdALoXqSA==} - - '@0xsequence/hooks@5.4.9': - resolution: {integrity: sha512-FhTD0CinRYoy3UVQJdwEfOh81BV4Xgs45aQw56Tr/a49y3BUZofe/kMfNsBE2fDXqLsjmpQ2DMEfAgkq0jp6kw==} + '@0xsequence/hooks@5.4.11': + resolution: {integrity: sha512-lAP+ryL1yXkMXKDWOVtEBMVnEM3Vm+Zob4fJkqcaSn7X9Mrhwiofrt923SHbk4a2S3pN6TQThM/vRMgzIOB8+g==} peerDependencies: - '@0xsequence/api': '>=2.3.38' - '@0xsequence/indexer': '>=2.3.38' - '@0xsequence/metadata': '>=2.3.38' - '@0xsequence/network': '>=2.3.38' + '@0xsequence/api': '>=2.3.43' + '@0xsequence/indexer': '>=2.3.43' + '@0xsequence/metadata': '>=2.3.43' + '@0xsequence/network': '>=2.3.43' '@tanstack/react-query': '>= 5' react: '>= 17' - react-dom: '>= 17' viem: '>= 2.44.0' - '@0xsequence/identity-instrument@3.0.0-beta.19': - resolution: {integrity: sha512-aAoEXt5+JQCNyZttyxBVpZQOQf80hSE0CngsOiVxekJQl6xD/pX2FteWCXiPQPAeXOMtn6HTa/qNw+FAIAZpmg==} - '@0xsequence/indexer@2.3.41': resolution: {integrity: sha512-zAclbFgafj9O8+t4x7UmyNQu359SHY32aOGRQWsl5E7TvrfgPrAfDMW8Rfsu++fNwEhIgOt5gkL0kbyvUGKtLQ==} - '@0xsequence/indexer@2.3.43': - resolution: {integrity: sha512-PBPEc+zsvEG8XOwvOOiMm+G1wmg2+20kfTTxOHD0TFMs6zx14gHbmhJjnfVMRTVVFoIrkSpy5g0g8Ia7yy8w6A==} + '@0xsequence/indexer@2.3.44': + resolution: {integrity: sha512-aNNvnkzjSFTjoFGp9UXdQgpG/F126r/frvsD+8nPS62eAOx2puuKEmy0/EKrervfGxVeqA8rcWc9phcLykGyZQ==} - '@0xsequence/indexer@3.0.5': - resolution: {integrity: sha512-T+I0ypBcRD3i4kruO0yylJ/gzynRieUtLopplyXJuaMJYQFuQZwkRbUxDpjPy0f6da+aSbPvCsA5PaIrfT9RKg==} + '@0xsequence/indexer@3.0.12': + resolution: {integrity: sha512-kgiu6hX23WTInluD6HqkR7WCKRAfQyPTimau+GeKHYiYh7WG0U3R6N00i5CJU3TUpHDqt+eVF5isK2fp2F8VXA==} - '@0xsequence/metadata@2.3.43': - resolution: {integrity: sha512-dwHcmNzNkroQs1bQHdkVZmcQPako6nyX0Bnnle2PIhkvmakht1nV0+Y4SmteYoInyNZlo2YT4LKbgReXBdleRw==} + '@0xsequence/metadata@2.3.44': + resolution: {integrity: sha512-Y+0U9V3OwHFjuh/GfF8WY/+Q/w9iZUHOBvb8kMwrHxqCyYXgOl1latLbzR/4E8rttrEqo51JRCvZA9lhMnraBA==} - '@0xsequence/metadata@3.0.5': - resolution: {integrity: sha512-MQO4hEb7jC7qv38f7fi9p5c/TPtjWwHuqPvlmbYVEibALnTWPl1Ux/UVkO+ncgo3RFWCtk/DRj7cDiNUfDpIcw==} + '@0xsequence/metadata@3.0.12': + resolution: {integrity: sha512-q7hP1UyXeHUufJgKMVr6UGkmmaugDVyM3u/sjZLBDzLgT6GNqu9Ss07c5E8eGeJmoSLwnwhRZyY5biah41sxMg==} - '@0xsequence/migration@2.3.43': - resolution: {integrity: sha512-b/KLW5bCtM9DW6HZr2k8CsPH6mhCAeKA69G9D5pix2lYzfpFfLgxPw6J98x48Rly2cM19WfHWUYUIL9myOyHaQ==} + '@0xsequence/migration@2.3.44': + resolution: {integrity: sha512-pXoBSQj5620m3KJVpkubg1/pGxihYmh5O1QcfDP5qpU77MSyGNdb0PvSY2WZoWRyHHNxa/sRyJ+Stv8eXPeOcQ==} peerDependencies: ethers: '>=6' @@ -377,13 +296,13 @@ packages: peerDependencies: ethers: '>=6' - '@0xsequence/network@2.3.43': - resolution: {integrity: sha512-HLorxJ/UIKcRcUPyyTxy4yeaioxc2hmm0joqClfY8tvweO/ASKXXa4aXCdSDWaLFbVQlhmrn4i1FR/ykwQM57A==} + '@0xsequence/network@2.3.44': + resolution: {integrity: sha512-nrRaJZbD3nGSuo4OtAy3xiAiCFCrQCiDXoJg8VWqVNCOA10r7LwyRGIs7v7cwr0/WjGLarqShkuogoPmgXakwA==} peerDependencies: ethers: '>=6' - '@0xsequence/provider@2.3.43': - resolution: {integrity: sha512-e5JvAjJ7rPrydVsfofloCjSeKIIKlHUr481373hC1TB7UmqfD2fIAbH4rYV80GCy0Ha+2n9B0iy/8xQtKwwj1Q==} + '@0xsequence/provider@2.3.44': + resolution: {integrity: sha512-+/LHbTJgOotbRQF5TgqBk8hrEZsp1lsr26YlSx62qNcJD5Nkr3dNco/M3/ND1ZHkGS5wqlu7mFjY/0bWrPNxfg==} peerDependencies: ethers: '>=6' @@ -392,70 +311,49 @@ packages: peerDependencies: ethers: '>=6' - '@0xsequence/relayer@2.3.43': - resolution: {integrity: sha512-2Rs1e6LA9nLRGAlQEcaCFscEvRNhp9MkryXyqarwbrojCg0tYk0WmQcicyjHUOqiKAHhjTn+MepuwnFslKMPqQ==} + '@0xsequence/relayer@2.3.44': + resolution: {integrity: sha512-Q8RukXpj94/G1SWP/xnRzL+BAlCJH7DmvsWbhJKED+RNVSE2xeFagD2F8zHGYu4nZgnGJpLFjBfgdcx1PiAFtA==} peerDependencies: ethers: '>=6' - '@0xsequence/relayer@3.0.0-beta.16': - resolution: {integrity: sha512-AThyuMWuvAJv64I2o38hJKtlRxzj51x8pYLWr70yqHkRi2CasHAEK5xEDhVJA9XCQ2g+XiKiBSezwsfNbStDVg==} - - '@0xsequence/relayer@3.0.0-beta.17': - resolution: {integrity: sha512-PP75DQmaTQeNNzhC7zG5tCcGe44hfPyNKVEu5VjtYRQhQk+wlF1TjYxHUTB4ywynrnvfMYLDDE4uF7I6wjjMTg==} - - '@0xsequence/replacer@2.3.43': - resolution: {integrity: sha512-LWD+UNRaz3gWV2MsQjaxui0WdCFrmBHzHIPMrfHTj5LnXBmSC2BUDYPGWTDhzZ9RPtNHoyg4eQRKLDVgEzWYLQ==} + '@0xsequence/replacer@2.3.44': + resolution: {integrity: sha512-cCVHQ/QVNQTGiyENhkIWTe6eYsCAnTtX9b8stx8Cde1FYcyG7mc6t5dPrezaA8KQg6qJIreIdg3UR1IPHBUEhw==} peerDependencies: ethers: '>=6' - '@0xsequence/sessions@2.3.43': - resolution: {integrity: sha512-7/1i2uqc1L2pdjgxmYUhNzsoyOj9e5sQsEj3kXZSc0OSAbPJk4jEegiNMdO7K8vBV53N1qFQ8ySm053lJFBcRg==} + '@0xsequence/sessions@2.3.44': + resolution: {integrity: sha512-IM7UWIW6eHuUohRXy78h8AwJtTlBAK4ODPQ0HBeaRqpI2NcShkWM2NhSawgqzZ3LBKwtFDl82VlM71ReIiHugw==} peerDependencies: ethers: '>=6' - '@0xsequence/signhub@2.3.43': - resolution: {integrity: sha512-vG4fFupdOoXo9u1Q9eKvvcVSIx3hb2viNnblj5LudYUTxwLS/EvmKcvMYnC2bLkjP5rF/yqi7uY5d8v19FIw3Q==} + '@0xsequence/signhub@2.3.44': + resolution: {integrity: sha512-gv75IoRFhEbhpBCpJ/TR0fUmfBfn/gf9Lvdsy3fLVIFMsm5x9krzbCC1rbmGyFSX/aijuFsnLN2rdJaR0wRM2g==} peerDependencies: ethers: '>=6' - '@0xsequence/tee-verifier@0.1.2': - resolution: {integrity: sha512-7sKr8/T4newknx6LAukjlRI3siGiGhBnZohz2Z3jX0zb0EBQdKUq0L//A7CPSckHFPxTg/QvQU2v8e9x9GfkDw==} - '@0xsequence/utils@2.3.41': resolution: {integrity: sha512-wikEOiYxfq+Iqsfb9JF6xHnpyXHaUre+2FUQpk3teo7/FXy0xtHdzxtfbhGn5/EcMnlSErk1nt6isrcxlkkHuQ==} peerDependencies: ethers: '>=6' - '@0xsequence/utils@2.3.43': - resolution: {integrity: sha512-b5+8kNY1sEUU6yICOEoMZIoM4PNzgxIObKdOlk22d8SGb//VB7k9/gpG+u4LYVrA4t3LHlSuzzt62MEQ3mFMYA==} + '@0xsequence/utils@2.3.44': + resolution: {integrity: sha512-gB3QgkR3hnF8Q9d5MnsvTAZ3u/Gwfh9D3eP8ayRiLNpqzkATBGhaPO72w0DYdU5b+ZO9+8sPpqLUw25ZeIKYhg==} peerDependencies: ethers: '>=6' - '@0xsequence/waas@2.3.43': - resolution: {integrity: sha512-/7XYyG93JlPoQVbTwGX/vUfXB/Hn4RXRA3dDA+gve9UxxKUHHsoklhCfinQmXVOQ55aVKOpGs9Qxf4JUG5Yt2g==} + '@0xsequence/waas@2.3.44': + resolution: {integrity: sha512-WpP6JBjhs4LOD7oA5xFZDgaPoWMCkc1TN3DrtBBX4cgB+T/F3DNHXwc29Ou2Bm01/l7SabPAOcAKwXoXLrH70A==} peerDependencies: ethers: '>=6' - '@0xsequence/wallet-core@3.0.0-beta.16': - resolution: {integrity: sha512-Vi34/n5FPVXfbz6ykoiATXaG/CAYyMbo3f01/t3NuyZc2DkgzZ7/fIlN6G2i2PEi2aV3gTt/ENVapOsJVRD/xw==} - - '@0xsequence/wallet-core@3.0.0-beta.17': - resolution: {integrity: sha512-0IKBI+25BUoDbi/m3/uehFMjM+WuF8RAXVfz3QUtp7hI/sA6v0+bFA2Gq/rQdtoB40HkZjxTtsMhKEzmxLZTPA==} - '@0xsequence/wallet-primitives@3.0.0-beta.16': resolution: {integrity: sha512-iwweQtEo/6sA6VBSVTQggdwKRvYoJOaRBrB+1trp05ULq4+rtvS+BG4mPfZQN86RWy93MYwCF1znsDon69u6wQ==} - '@0xsequence/wallet-primitives@3.0.0-beta.17': - resolution: {integrity: sha512-AjdckQi1tgqgHG55XvilfkINB0TTooCC2j5bHNB+FQyk30XwFCH7N6oUt55BzDycckHHrDhixsT7ua2V2/xxWg==} - '@0xsequence/wallet-primitives@3.0.0-beta.19': resolution: {integrity: sha512-YJmwI9ECnidGVmSeKKiCdkaZ5MUg7+awHdG7+tW6U2gXGlY+8gJ5yNy8jX+GwoR6kMsWZh+ZuKFBUSqQjntYOQ==} - '@0xsequence/wallet-wdk@3.0.0-beta.17': - resolution: {integrity: sha512-tqunDMEu+LqNIt3Zbt6yrE6bb8tFs2aqk+fha0Tp7x8VOYGcgrPBiVOF48jjwljtzOk2tO/yu/tETH7wHIzX6Q==} - - '@0xsequence/wallet@2.3.43': - resolution: {integrity: sha512-zbS7p6SdZRaVU6nEVD72y6TOZlCny3s3JYx/pAn0gUxSKOuioidG+iO/pZ6Z8vmKAEAFyIUXWdcbefk+wi3ocw==} + '@0xsequence/wallet@2.3.44': + resolution: {integrity: sha512-rpQ9Iy9MwHc6UjX8ZJGCnofe6xPI41LtpTxphht6sWyegZb/G19XOBBadqLqFEwGqyE2rBt2Lh7X9/9Fg2xjyw==} peerDependencies: ethers: '>=6' @@ -482,69 +380,86 @@ packages: resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.29.0': - resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} - '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + '@babel/generator@7.29.7': + resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} engines: {node: '>=6.9.0'} - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.28.6': - resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.0': - resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.24.1': + resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-transform-react-jsx-self@7.27.1': - resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + '@babel/plugin-transform-react-jsx-self@7.29.7': + resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-source@7.27.1': - resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + '@babel/plugin-transform-react-jsx-source@7.29.7': + resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -553,18 +468,22 @@ packages: resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + '@babel/traverse@7.29.7': + resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} engines: {node: '>=6.9.0'} '@babel/types@7.29.0': resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + '@base-org/account@2.4.0': resolution: {integrity: sha512-A4Umpi8B9/pqR78D1Yoze4xHyQaujioVRqqO3d6xuDFw9VRtjg6tK3bPlwE0aW+nVH/ntllCpPa2PbI8Rnjcug==} @@ -623,54 +542,11 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} - '@cloudflare/kv-asset-handler@0.4.2': - resolution: {integrity: sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==} - engines: {node: '>=18.0.0'} - - '@cloudflare/unenv-preset@2.14.0': - resolution: {integrity: sha512-XKAkWhi1nBdNsSEoNG9nkcbyvfUrSjSf+VYVPfOto3gLTZVc3F4g6RASCMh6IixBKCG2yDgZKQIHGKtjcnLnKg==} - peerDependencies: - unenv: 2.0.0-rc.24 - workerd: ^1.20260218.0 - peerDependenciesMeta: - workerd: - optional: true - - '@cloudflare/workerd-darwin-64@1.20260305.0': - resolution: {integrity: sha512-chhKOpymo0Eh9J3nymrauMqKGboCc4uz/j0gA1G4gioMnKsN2ZDKJ+qjRZDnCoVGy8u2C4pxlmyIfsXCAfIzhQ==} - engines: {node: '>=16'} - cpu: [x64] - os: [darwin] - - '@cloudflare/workerd-darwin-arm64@1.20260305.0': - resolution: {integrity: sha512-K9aG2OQk5bBfOP+fyGPqLcqZ9OR3ra6uwnxJ8f2mveq2A2LsCI7ZeGxQiAj75Ti80ytH/gJffZIx4Np2JtU3aQ==} - engines: {node: '>=16'} - cpu: [arm64] - os: [darwin] - - '@cloudflare/workerd-linux-64@1.20260305.0': - resolution: {integrity: sha512-tt7XUoIw/cYFeGbkPkcZ6XX1aZm26Aju/4ih+DXxOosbBeGshFSrNJDBfAKKOvkjsAZymJ+WWVDBU+hmNaGfwA==} - engines: {node: '>=16'} - cpu: [x64] - os: [linux] - - '@cloudflare/workerd-linux-arm64@1.20260305.0': - resolution: {integrity: sha512-72QTkY5EzylmvCZ8ZTrnJ9DctmQsfSof1OKyOWqu/pv/B2yACfuPMikq8RpPxvVu7hhS0ztGP6ZvXz72Htq4Zg==} - engines: {node: '>=16'} - cpu: [arm64] - os: [linux] - - '@cloudflare/workerd-windows-64@1.20260305.0': - resolution: {integrity: sha512-BA0uaQPOaI2F6mJtBDqplGnQQhpXCzwEMI33p/TnDxtSk9u8CGIfBFuI6uqo8mJ6ijIaPjeBLGOn2CiRMET4qg==} - engines: {node: '>=16'} - cpu: [x64] - os: [win32] - '@cloudflare/workers-types@4.20260317.1': resolution: {integrity: sha512-+G4eVwyCpm8Au1ex8vQBCuA9wnwqetz4tPNRoB/53qvktERWBRMQnrtvC1k584yRE3emMThtuY0gWshvSJ++PQ==} - '@coinbase/cdp-sdk@1.45.0': - resolution: {integrity: sha512-4fgGOhyN9g/pTDE9NtsKUapwFsubrk9wafz8ltmBqSwWqLZWfWxXkVmzMYYFAf+qeGf/X9JqJtmvDVaHFlXWlw==} + '@coinbase/cdp-sdk@1.51.2': + resolution: {integrity: sha512-o4IEwXbyAjfhPQWoFBuqnV1JQGLk4NlUVMzH/ur4voPSjYZvlYFVuOoE/eEcsoPFN28xaWTBvqebwncQL8h8fQ==} '@coinbase/wallet-sdk@3.9.3': resolution: {integrity: sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw==} @@ -755,16 +631,12 @@ packages: resolution: {integrity: sha512-aO5l99BQJ0X34ft8b0h7QFkQlqxC6e7ZPVmBKz13xM9O8obDaM1Cld4sQlJDXXU/VFuUzQ30mVtHjVz74TuStw==} engines: {node: '>=v18'} - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - '@databeat/tracker@0.9.3': resolution: {integrity: sha512-eGsiNU/CRFujcNtUUqvBiqveCs6S6SiAhalXPDodbk74d3FzvLqHDn5k6WfOEJIhrP3CbYgfMXL0nk51s/rQsg==} - '@ecies/ciphers@0.2.5': - resolution: {integrity: sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A==} - engines: {bun: '>=1', deno: '>=2', node: '>=16'} + '@ecies/ciphers@0.2.6': + resolution: {integrity: sha512-patgsRPKGkhhoBjETV4XxD0En4ui5fbX0hzayqI3M8tvNMGUoUvmyYAIWwlxBc1KX5cturfqByYdj5bYGRpN9g==} + engines: {bun: '>=1', deno: '>=2.7.10', node: '>=16'} peerDependencies: '@noble/ciphers': ^1.0.0 @@ -1405,159 +1277,6 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@img/colour@1.1.0': - resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} - engines: {node: '>=18'} - - '@img/sharp-darwin-arm64@0.34.5': - resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [darwin] - - '@img/sharp-darwin-x64@0.34.5': - resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-darwin-arm64@1.2.4': - resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} - cpu: [arm64] - os: [darwin] - - '@img/sharp-libvips-darwin-x64@1.2.4': - resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} - cpu: [x64] - os: [darwin] - - '@img/sharp-libvips-linux-arm64@1.2.4': - resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-arm@1.2.4': - resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-ppc64@1.2.4': - resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-riscv64@1.2.4': - resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-s390x@1.2.4': - resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linux-x64@1.2.4': - resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@img/sharp-linux-arm64@0.34.5': - resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-arm@0.34.5': - resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-ppc64@0.34.5': - resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-riscv64@0.34.5': - resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-s390x@0.34.5': - resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@img/sharp-linux-x64@0.34.5': - resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@img/sharp-linuxmusl-arm64@0.34.5': - resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@img/sharp-linuxmusl-x64@0.34.5': - resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [linux] - libc: [musl] - - '@img/sharp-wasm32@0.34.5': - resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [wasm32] - - '@img/sharp-win32-arm64@0.34.5': - resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [win32] - - '@img/sharp-win32-ia32@0.34.5': - resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [ia32] - os: [win32] - - '@img/sharp-win32-x64@0.34.5': - resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [x64] - os: [win32] - '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} engines: {node: '>=18'} @@ -1586,11 +1305,8 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - - '@lit-labs/ssr-dom-shim@1.5.1': - resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==} + '@lit-labs/ssr-dom-shim@1.6.0': + resolution: {integrity: sha512-VHb0ALPMTlgKjM6yIxxoQNnpKyUKLD04VzeQdsiXkMqkvYlAHxq9glGLmgbb889/1GsohSOAjvQYoiBppXFqrQ==} '@lit/reactive-element@2.1.2': resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} @@ -1601,8 +1317,8 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} - '@meshconnect/node-api@2.0.24': - resolution: {integrity: sha512-FXQisYc2QCyHK2IpA3H9fXwidWNbcBAD6hKIoMP4elicBb+owmr5fSnoBwqcBqhVCeZQh0yjcfPbI9xQET17TQ==} + '@meshconnect/node-api@2.0.27': + resolution: {integrity: sha512-D1MEfDUE9NHPuzwVQ91HkNe4Y/vmORNyj1CWHzoXUxH/pMIrcxnhYf2O5skRCNpLR1ABYXV6KDaSr6zgTg4cgw==} '@meshconnect/uwc-bridge-parent@1.1.1': resolution: {integrity: sha512-Hx5ft4hEn50VUALZe06zcSzqBh6KUl5A1AGzy1AtCF3wVkRR/gpO4FJB3M1u1YapmEEGG6C6LW7LnUk58dzW/Q==} @@ -1674,12 +1390,12 @@ packages: resolution: {integrity: sha512-1mcOQVGr9rSrVcbKPNVzbZ8eCl1K0FATsYH3WJ/MH4WcZDWGECWrXJPNMZoEAkLxWiMe8jOQBumg2pmcDa9zpQ==} deprecated: No longer maintained, superseded by https://docs.metamask.io/metamask-connect - '@metamask/superstruct@3.2.1': - resolution: {integrity: sha512-fLgJnDOXFmuVlB38rUN5SmU7hAFQcCjrg3Vrxz67KTY7YHFnSNEKvX4avmEBdOI0yTCxZjwMCFEqsC8k2+Wd3g==} + '@metamask/superstruct@3.3.0': + resolution: {integrity: sha512-P/MwKoAIHGgMz7gnfIV9jP0wG8f/bCHooy5LPfYWzoyV9FrcHB/9Ai/spIOa6jRmoSr+R6etWvulTakDfwCbrA==} engines: {node: '>=16.0.0'} - '@metamask/utils@11.10.0': - resolution: {integrity: sha512-+bWmTOANx1MbBW6RFM8Se4ZoigFYGXiuIrkhjj4XnG5Aez8uWaTSZ76yn9srKKClv+PoEVoAuVtcUOogFEMUNA==} + '@metamask/utils@11.11.0': + resolution: {integrity: sha512-0nF2CWjWQr/m0Y2t2lJnBTU1/CZPPTvKvcESLplyWe/tyeb8zFOi/FeneDmaFnML6LYRIGZU6f+xR0jKAIUZfw==} engines: {node: ^18.18 || ^20.14 || >=22} '@metamask/utils@5.0.2': @@ -1728,97 +1444,97 @@ packages: '@package-json/types@0.0.12': resolution: {integrity: sha512-uu43FGU34B5VM9mCNjXCwLaGHYjXdNincqKLaraaCW+7S2+SmiBg1Nv8bPnmschrIfZmfKNY9f3fC376MRrObw==} - '@parcel/watcher-android-arm64@2.5.6': - resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} + '@parcel/watcher-android-arm64@2.5.1': + resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [android] - '@parcel/watcher-darwin-arm64@2.5.6': - resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==} + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [darwin] - '@parcel/watcher-darwin-x64@2.5.6': - resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==} + '@parcel/watcher-darwin-x64@2.5.1': + resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [darwin] - '@parcel/watcher-freebsd-x64@2.5.6': - resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==} + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [freebsd] - '@parcel/watcher-linux-arm-glibc@2.5.6': - resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==} + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] libc: [glibc] - '@parcel/watcher-linux-arm-musl@2.5.6': - resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] libc: [musl] - '@parcel/watcher-linux-arm64-glibc@2.5.6': - resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - '@parcel/watcher-linux-arm64-musl@2.5.6': - resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] libc: [musl] - '@parcel/watcher-linux-x64-glibc@2.5.6': - resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] libc: [glibc] - '@parcel/watcher-linux-x64-musl@2.5.6': - resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] libc: [musl] - '@parcel/watcher-win32-arm64@2.5.6': - resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} + '@parcel/watcher-win32-arm64@2.5.1': + resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [win32] - '@parcel/watcher-win32-ia32@2.5.6': - resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==} + '@parcel/watcher-win32-ia32@2.5.1': + resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} engines: {node: '>= 10.0.0'} cpu: [ia32] os: [win32] - '@parcel/watcher-win32-x64@2.5.6': - resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==} + '@parcel/watcher-win32-x64@2.5.1': + resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [win32] - '@parcel/watcher@2.5.6': - resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} + '@parcel/watcher@2.5.1': + resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} engines: {node: '>= 10.0.0'} '@paulmillr/qr@0.2.1': resolution: {integrity: sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ==} - deprecated: 'The package is now available as "qr": npm install qr' + deprecated: 'Switch to "qr" (new package name) for security updates: npm install qr' '@polygonlabs/apps-team-lint@2.0.2': resolution: {integrity: sha512-vMfjNcPQpR8WEXt+/YG781Ktym82XPrKkGwfgqLBk53Gx18VBzO113wZuFvvpKHZXg8lzqSIY8UgJowcJUaxtw==} @@ -1829,6 +1545,10 @@ packages: typescript: optional: true + '@polygonlabs/oms-wallet@0.2.0': + resolution: {integrity: sha512-kLsBfrwXK8m7Zd2CzQ6+p/rOQE5ckeEN//Lc1F7Jq9E80ve/EXoVjWujK+DP4weMfhaHwWiK8+VllviuUvZgVA==} + engines: {node: '>=22'} + '@polymarket/clob-client-v2@1.0.2': resolution: {integrity: sha512-lC80Esug6s6y3uV8D5HnkxoXVZUnATjyP6PcK2IXO740iGDuLlp9Dvvkx3+VVygHahN+M3NY7JiYiTQkDfWoeQ==} @@ -1845,21 +1565,28 @@ packages: '@ethersproject/providers': ^5.0.14 '@ethersproject/solidity': ^5.0.7 - '@poppinss/colors@4.1.6': - resolution: {integrity: sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==} - - '@poppinss/dumper@0.6.5': - resolution: {integrity: sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==} - - '@poppinss/exception@1.2.3': - resolution: {integrity: sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==} - - '@radix-ui/number@1.1.1': - resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} + '@radix-ui/number@1.1.2': + resolution: {integrity: sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==} '@radix-ui/primitive@1.1.3': resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + '@radix-ui/primitive@1.1.4': + resolution: {integrity: sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ==} + + '@radix-ui/react-arrow@1.1.11': + resolution: {integrity: sha512-Kdil9BB1rIFC/khmf4hC35bn8701AJcizTU7G7cUbEbk5XqqbjDuHW60uUfKqO5WojjZcbAW51Q7P0hRmMLw8A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-arrow@1.1.7': resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} peerDependencies: @@ -1873,8 +1600,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-aspect-ratio@1.1.8': - resolution: {integrity: sha512-5nZrJTF7gH+e0nZS7/QxFz6tJV4VimhQb1avEgtsJxvvIp5JilL+c58HICsKzPxghdwaDt48hEfPM1au4zGy+w==} + '@radix-ui/react-aspect-ratio@1.1.11': + resolution: {integrity: sha512-IUAhIVpBUvP5NNICjlaB1OFmtRLGqQqTF3ZOSGPoq3XeLXRFtHiWTRxSVEULgOd9GQR2c7tsYqDnhUennapZnw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1886,8 +1613,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-checkbox@1.3.3': - resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==} + '@radix-ui/react-checkbox@1.3.6': + resolution: {integrity: sha512-eUEUoGMDpfkgHWSE97ZZaUJtzR1M7EKnNIpD1Q16+8JR9NWghcaqMulx9PuCQ720w0UclfYn6FEbCdd5Hx087g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1899,8 +1626,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collapsible@1.1.12': - resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} + '@radix-ui/react-collapsible@1.1.15': + resolution: {integrity: sha512-8A1zibu5skAQ+UVbaeNH5hVMibiFCRJzgMuM14LTWGttnTZKQL9jwYnhAbHRuxrtCqPXa4JvvnVUq1pTNgyZYw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1912,8 +1639,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collection@1.1.7': - resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} + '@radix-ui/react-collection@1.1.11': + resolution: {integrity: sha512-djW9+zeg137KQdlPtmE8xnaD+K2rcXXMWFrSg0hsmYZ6HRbdTA7tDHFgpaW9+huWVEu0RCabL+985T4TA0BE7g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1934,6 +1661,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-compose-refs@1.1.3': + resolution: {integrity: sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-context@1.1.2': resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} peerDependencies: @@ -1943,8 +1679,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-context@1.1.3': - resolution: {integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==} + '@radix-ui/react-context@1.1.4': + resolution: {integrity: sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1952,8 +1688,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-dialog@1.1.15': - resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} + '@radix-ui/react-dialog@1.1.18': + resolution: {integrity: sha512-apa28mldjMgORmE6g/w3sCcA0Y9UAVeeDVoozN4i7kOw12mLl9RBchfzK3Nn6qxOWjrZhK1Lfy7f07kyzxtnBw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1965,8 +1701,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-direction@1.1.1': - resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} + '@radix-ui/react-direction@1.1.2': + resolution: {integrity: sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1987,8 +1723,21 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dropdown-menu@2.1.16': - resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} + '@radix-ui/react-dismissable-layer@1.1.14': + resolution: {integrity: sha512-4lUhWTWAjbDIqFrAPWJ3WqBOpO5YchVZ88X3nh6H9Lu5AFi5nCUeTPj3D8FSDmabmFeRe9ME0BDA4MwKTha5GQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-dropdown-menu@2.1.19': + resolution: {integrity: sha512-HZccBkbK0LOi8nYKIp5jll/zIRW0cCOmG6WWyqsSpmXCU+ZlcBbTqIwlBvPCu886C5RVu6c/kHV7xSP8IgYNHw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2000,8 +1749,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-focus-guards@1.1.3': - resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} + '@radix-ui/react-focus-guards@1.1.4': + resolution: {integrity: sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -2009,8 +1758,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-focus-scope@1.1.7': - resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} + '@radix-ui/react-focus-scope@1.1.11': + resolution: {integrity: sha512-Mn88Vg2whaRocGJNOH+DKFqYm6ySFPQaiwHNxZPyjn99B52KAEJWWY9NP83+nWdk2HM3rdov+STu9AG471Rt9w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2031,8 +1780,17 @@ packages: '@types/react': optional: true - '@radix-ui/react-menu@2.1.16': - resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} + '@radix-ui/react-id@1.1.2': + resolution: {integrity: sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-menu@2.1.19': + resolution: {integrity: sha512-Mht9BVd1AIsNFVQr4KG3bIK7XQn5IXF0TL/2ObsrzOdc1loaly/+kBDL5roSCYn8j8XZkvpOD0WYLz2FQtH1Eg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2057,6 +1815,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-popper@1.3.2': + resolution: {integrity: sha512-3QXNeMkdshed1MR3LNoiCirBywRFPkD8ETJa/HlPuLwSajaQixf2ro+isoDNJlGABg9ug41XuZpINZJIle4XWg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-portal@1.1.13': + resolution: {integrity: sha512-z3oXfmaHLJTF1wktbjgD6cn9jiEbq3WSondB10LIuIt2m2Ym4iJlrW04/euMwENDdWDdE7z+OuY7Qyp1YpRSwA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-portal@1.1.9': resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} peerDependencies: @@ -2083,6 +1867,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-presence@1.1.6': + resolution: {integrity: sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-primitive@2.1.3': resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} peerDependencies: @@ -2096,8 +1893,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-primitive@2.1.4': - resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==} + '@radix-ui/react-primitive@2.1.7': + resolution: {integrity: sha512-bC3NiwsprbxKjuon9l7X6BUTw7FPVzEYaL92MPEY5SCd/9hUTPXVFtVwRix7778wtRsVao+zE062gL79FZleeQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2109,8 +1906,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-progress@1.1.8': - resolution: {integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==} + '@radix-ui/react-progress@1.1.11': + resolution: {integrity: sha512-KqiGJcFaZDc+BvveAgU3ZhACg2MvSUDrCBx4lRR/ZVRNal0bvt8lBpvnSkep9heeOuF8Qfw3fszLDX4OpQ2NVw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2122,8 +1919,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-radio-group@1.3.8': - resolution: {integrity: sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==} + '@radix-ui/react-radio-group@1.4.2': + resolution: {integrity: sha512-W8Uo9riHnlzLLWy+r2mVHUyuEWqD/+be4PZzbEvaGoFSBDHkm+GYWjtcE6u3AmPKNyfanWpnVfpZ2GqPCdzzsw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2135,8 +1932,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-roving-focus@1.1.11': - resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} + '@radix-ui/react-roving-focus@1.1.14': + resolution: {integrity: sha512-8Qcnx9447tx/aCBgw6Jenfqg4Skq+vqab9mCBmuGNipIS5YXvL275wbKEu7+ICYHIlAPgCduUMJH1XOYewKF6Q==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2148,8 +1945,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-select@2.2.6': - resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==} + '@radix-ui/react-select@2.3.2': + resolution: {integrity: sha512-brXD6C/V0fVK0DDbscLVw6LsXrjQ+ay8jdOBaN+tLb4vsHsAMm6Gt6eT77wHX1Eq8GPtD5rJ+RxFtfDozsb4+Q==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2170,8 +1967,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-slot@1.2.4': - resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} + '@radix-ui/react-slot@1.3.0': + resolution: {integrity: sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -2179,8 +1976,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-switch@1.2.6': - resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} + '@radix-ui/react-switch@1.3.2': + resolution: {integrity: sha512-tgRBI3DdNwAJYE4BBZyZcz/HRRCvAsPkRvG1wvKc+41tBGMxPn/a87T/wikXAvyDypNQ9kaZwHbeZe+veHCGpA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2192,8 +1989,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-tabs@1.1.13': - resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} + '@radix-ui/react-tabs@1.1.16': + resolution: {integrity: sha512-v3Ab2l7z6U7tRB4xA0IyKdq0OsqaO1o9ZjsIEoKKnSZ/l96mZz8aCTX0NCXw+YVHJXr8Km4d+Mn6/Q8YjXa+gw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2205,8 +2002,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-toast@1.2.15': - resolution: {integrity: sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==} + '@radix-ui/react-toast@1.2.18': + resolution: {integrity: sha512-YNEnTHV47hPep+U0QvVM02OJNka9uygREc+k4Nh5VSZBg4MmE+myI442x3hCGfRpX7N2WSSYSJKws4gE+Z8lgg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2240,8 +2037,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-controllable-state@1.2.2': - resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + '@radix-ui/react-use-callback-ref@1.1.2': + resolution: {integrity: sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -2249,8 +2046,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-effect-event@0.0.2': - resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -2258,8 +2055,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-escape-keydown@1.1.1': - resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} + '@radix-ui/react-use-controllable-state@1.2.3': + resolution: {integrity: sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -2267,8 +2064,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-layout-effect@1.1.1': - resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -2276,8 +2073,44 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-previous@1.1.1': - resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} + '@radix-ui/react-use-effect-event@0.0.3': + resolution: {integrity: sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.2': + resolution: {integrity: sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-previous@1.1.2': + resolution: {integrity: sha512-IGBQPtRFdhN6MQ8dbegVmBq1LVZluya3F1jWY+puIcQC3MHctRwTDSBWCkL/3ZcnMJLTMJ++Z+ktmvg0F89iCw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -2294,6 +2127,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-rect@1.1.2': + resolution: {integrity: sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-size@1.1.1': resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} peerDependencies: @@ -2303,6 +2145,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-size@1.1.2': + resolution: {integrity: sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-visually-hidden@1.2.3': resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} peerDependencies: @@ -2316,8 +2167,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-visually-hidden@1.2.4': - resolution: {integrity: sha512-kaeiyGCe844dkb9AVF+rb4yTyb1LiLN/e3es3nLiRyN4dC8AduBYPMnnNlDjX2VDOcvDEiPnRNMJeWCfsX0txg==} + '@radix-ui/react-visually-hidden@1.2.7': + resolution: {integrity: sha512-1wNZBggTDK3GRuuQ6nP4k2yi7a6l7I5qbMPbZcRsrGsGVead/f/d5FhEzUvqFs0bcrDLx7n1zKQ3JvLR6whaaw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2332,6 +2183,9 @@ packages: '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@radix-ui/rect@1.1.2': + resolution: {integrity: sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==} + '@react-oauth/google@0.11.1': resolution: {integrity: sha512-tywZisXbsdaRBVbEu0VX6dRbOSL2I6DgY97woq5NMOOOz+xtDsm418vqq+Vx10KMtra3kdHMRMf0hXLWrk2RMg==} peerDependencies: @@ -2370,141 +2224,141 @@ packages: '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} - '@rollup/rollup-android-arm-eabi@4.59.0': - resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + '@rollup/rollup-android-arm-eabi@4.62.2': + resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.59.0': - resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + '@rollup/rollup-android-arm64@4.62.2': + resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.59.0': - resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + '@rollup/rollup-darwin-arm64@4.62.2': + resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.59.0': - resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + '@rollup/rollup-darwin-x64@4.62.2': + resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.59.0': - resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + '@rollup/rollup-freebsd-arm64@4.62.2': + resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.59.0': - resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + '@rollup/rollup-freebsd-x64@4.62.2': + resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.59.0': - resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + '@rollup/rollup-linux-arm64-gnu@4.62.2': + resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.59.0': - resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + '@rollup/rollup-linux-arm64-musl@4.62.2': + resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.59.0': - resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + '@rollup/rollup-linux-loong64-gnu@4.62.2': + resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-loong64-musl@4.59.0': - resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + '@rollup/rollup-linux-loong64-musl@4.62.2': + resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} cpu: [loong64] os: [linux] libc: [musl] - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.59.0': - resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + '@rollup/rollup-linux-ppc64-musl@4.62.2': + resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} cpu: [ppc64] os: [linux] libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.59.0': - resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + '@rollup/rollup-linux-riscv64-musl@4.62.2': + resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.59.0': - resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + '@rollup/rollup-linux-s390x-gnu@4.62.2': + resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.59.0': - resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + '@rollup/rollup-linux-x64-gnu@4.62.2': + resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.59.0': - resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + '@rollup/rollup-linux-x64-musl@4.62.2': + resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.59.0': - resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + '@rollup/rollup-openbsd-x64@4.62.2': + resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.59.0': - resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + '@rollup/rollup-openharmony-arm64@4.62.2': + resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.59.0': - resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + '@rollup/rollup-win32-arm64-msvc@4.62.2': + resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.59.0': - resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + '@rollup/rollup-win32-ia32-msvc@4.62.2': + resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.59.0': - resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + '@rollup/rollup-win32-x64-gnu@4.62.2': + resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.59.0': - resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + '@rollup/rollup-win32-x64-msvc@4.62.2': + resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} cpu: [x64] os: [win32] @@ -2517,6 +2371,7 @@ packages: '@safe-global/safe-gateway-typescript-sdk@3.23.1': resolution: {integrity: sha512-6ORQfwtEJYpalCeVO21L4XXGSdbEMfyp2hEv6cP82afKXSwvse6d3sdelgaPWUxHIsFRkWvHDdzh8IyyKHZKxw==} engines: {node: '>=16'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. '@scure/base@1.1.9': resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} @@ -2546,10 +2401,6 @@ packages: resolution: {integrity: sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==} engines: {node: '>=18'} - '@sindresorhus/is@7.2.0': - resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} - engines: {node: '>=18'} - '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} @@ -2947,21 +2798,21 @@ packages: peerDependencies: '@solana/web3.js': ^1.98.0 - '@solana/wallet-standard-chains@1.1.1': - resolution: {integrity: sha512-Us3TgL4eMVoVWhuC4UrePlYnpWN+lwteCBlhZDUhFZBJ5UMGh94mYPXno3Ho7+iHPYRtuCi/ePvPcYBqCGuBOw==} - engines: {node: '>=16'} + '@solana/wallet-standard-chains@1.1.2': + resolution: {integrity: sha512-EZobEGclDBAFplpJC5F3d/s8Xnlqc5isNKuPrd5o9ZPZ7tWN84O0e68yIZ8MAOj9V7ieRadNiHtql7uIXCTyXg==} + engines: {node: '>=22'} - '@solana/wallet-standard-features@1.3.0': - resolution: {integrity: sha512-ZhpZtD+4VArf6RPitsVExvgkF+nGghd1rzPjd97GmBximpnt1rsUxMOEyoIEuH3XBxPyNB6Us7ha7RHWQR+abg==} - engines: {node: '>=16'} + '@solana/wallet-standard-features@1.4.0': + resolution: {integrity: sha512-f0tAdqwM2aL6CiFbIgt9h5zKFp+mgY/iNGwoxPMTj9VSTeQj7d1GGSmWhZw0XWoZ4N/1tnKTKmYFq+Dyq08jRw==} + engines: {node: '>=22'} - '@solana/wallet-standard-util@1.1.2': - resolution: {integrity: sha512-rUXFNP4OY81Ddq7qOjQV4Kmkozx4wjYAxljvyrqPx8Ycz0FYChG/hQVWqvgpK3sPsEaO/7ABG1NOACsyAKWNOA==} - engines: {node: '>=16'} + '@solana/wallet-standard-util@1.1.3': + resolution: {integrity: sha512-aweR5y5FjYaeS9TkoqAWERFpGUj2MJepsDhcekCuoPLcNCquJL85Nsnuy01tBybspN5+Y09SWkxwsODOFGSfkg==} + engines: {node: '>=22'} - '@solana/wallet-standard-wallet-adapter-base@1.1.4': - resolution: {integrity: sha512-Q2Rie9YaidyFA4UxcUIxUsvynW+/gE2noj/Wmk+IOwDwlVrJUAXCvFaCNsPDSyKoiYEKxkSnlG13OA1v08G4iw==} - engines: {node: '>=16'} + '@solana/wallet-standard-wallet-adapter-base@1.1.5': + resolution: {integrity: sha512-dbk+4mJAsZ1a2R/v5/Qvp6SleviuSNWd9LnuQ0ekH0HRRJTOWyTBJsdQsVDdAymdPnLAaIN5J10ni1CT2Z+ERg==} + engines: {node: '>=22'} peerDependencies: '@solana/web3.js': ^1.98.0 bs58: ^6.0.0 @@ -2969,9 +2820,6 @@ packages: '@solana/web3.js@1.98.4': resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==} - '@speed-highlight/core@1.2.14': - resolution: {integrity: sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA==} - '@spruceid/siwe-parser@2.1.2': resolution: {integrity: sha512-d/r3S1LwJyMaRAKQ0awmo9whfXeE88Qt00vRj91q5uv5ATtWIQEGJ67Yr5eSZw5zp1/fZCXZYuEckt8lSkereQ==} @@ -2987,149 +2835,76 @@ packages: '@stablelib/wipe@1.0.1': resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} - '@swc/helpers@0.5.20': - resolution: {integrity: sha512-2egEBHUMasdypIzrprsu8g+OEVd7Vp2MM3a2eVlM/cyFYto0nGz5BX5BTgh/ShZZI9ed+ozEq+Ngt+rgmUs8tw==} + '@swc/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} - '@tailwindcss/cli@4.2.2': - resolution: {integrity: sha512-iJS+8kAFZ8HPqnh0O5DHCLjo4L6dD97DBQEkrhfSO4V96xeefUus2jqsBs1dUMt3OU9Ks4qIkiY0mpL5UW+4LQ==} + '@tailwindcss/cli@4.3.2': + resolution: {integrity: sha512-Fzt+HrIZHDlkRYKdLMBeufaroaPvwCBG70sMLdmurdeadNMO/LxbmT8Sbb+P83ep0iAlAImettb7Y+rO+37rXw==} hasBin: true - '@tailwindcss/node@4.2.1': - resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==} - - '@tailwindcss/node@4.2.2': - resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} - - '@tailwindcss/oxide-android-arm64@4.2.1': - resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [android] + '@tailwindcss/node@4.3.2': + resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} - '@tailwindcss/oxide-android-arm64@4.2.2': - resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==} + '@tailwindcss/oxide-android-arm64@4.3.2': + resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} engines: {node: '>= 20'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.2.1': - resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - '@tailwindcss/oxide-darwin-arm64@4.2.2': - resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==} + '@tailwindcss/oxide-darwin-arm64@4.3.2': + resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.2.1': - resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] - - '@tailwindcss/oxide-darwin-x64@4.2.2': - resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==} + '@tailwindcss/oxide-darwin-x64@4.3.2': + resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==} engines: {node: '>= 20'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.2.1': - resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==} - engines: {node: '>= 20'} - cpu: [x64] - os: [freebsd] - - '@tailwindcss/oxide-freebsd-x64@4.2.2': - resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==} + '@tailwindcss/oxide-freebsd-x64@4.3.2': + resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': - resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==} - engines: {node: '>= 20'} - cpu: [arm] - os: [linux] - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': - resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==} engines: {node: '>= 20'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': - resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': - resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==} + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-arm64-musl@4.2.1': - resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [musl] - '@tailwindcss/oxide-linux-arm64-musl@4.2.2': - resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@tailwindcss/oxide-linux-x64-gnu@4.2.1': - resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@tailwindcss/oxide-linux-x64-gnu@4.2.2': - resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-x64-musl@4.2.1': - resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@tailwindcss/oxide-linux-x64-musl@4.2.2': - resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} + '@tailwindcss/oxide-linux-x64-musl@4.3.2': + resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [musl] - '@tailwindcss/oxide-wasm32-wasi@4.2.1': - resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - bundledDependencies: - - '@napi-rs/wasm-runtime' - - '@emnapi/core' - - '@emnapi/runtime' - - '@tybys/wasm-util' - - '@emnapi/wasi-threads' - - tslib - - '@tailwindcss/oxide-wasm32-wasi@4.2.2': - resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} + '@tailwindcss/oxide-wasm32-wasi@4.3.2': + resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -3140,62 +2915,46 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': - resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [win32] - - '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': - resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==} + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==} engines: {node: '>= 20'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.2.1': - resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==} - engines: {node: '>= 20'} - cpu: [x64] - os: [win32] - - '@tailwindcss/oxide-win32-x64-msvc@4.2.2': - resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==} + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==} engines: {node: '>= 20'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.2.1': - resolution: {integrity: sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==} - engines: {node: '>= 20'} - - '@tailwindcss/oxide@4.2.2': - resolution: {integrity: sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==} + '@tailwindcss/oxide@4.3.2': + resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==} engines: {node: '>= 20'} - '@tailwindcss/vite@4.2.1': - resolution: {integrity: sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==} + '@tailwindcss/vite@4.3.2': + resolution: {integrity: sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==} peerDependencies: - vite: ^5.2.0 || ^6 || ^7 + vite: ^5.2.0 || ^6 || ^7 || ^8 - '@tanstack/query-core@5.95.2': - resolution: {integrity: sha512-o4T8vZHZET4Bib3jZ/tCW9/7080urD4c+0/AUaYVpIqOsr7y0reBc1oX3ttNaSW5mYyvZHctiQ/UOP2PfdmFEQ==} + '@tanstack/query-core@5.101.2': + resolution: {integrity: sha512-hH5MLoJhF7KaIGd7q3xTXGXvslI+GYlM1Z/35aSHHWaCJWB7XvTSHYuV3eM7tw+aE0mT/xMro4M4Q9rCGHT0lw==} - '@tanstack/query-persist-client-core@5.95.2': - resolution: {integrity: sha512-Opfj34WZ594YXpEcZEs8WBiyPGrjrKlGILfk/Ss283uwWQ36C5nX3tRY/bBiXmM82KWauUuNvahwGwiyco/8cQ==} + '@tanstack/query-persist-client-core@5.101.2': + resolution: {integrity: sha512-rgMsbvBVpSPDUsprC9FYxojdG0Q1LH6yq1i3DXz2aps4VEqv2l4Msj3YDqIifU3xkl/DrYe9YWntZAJLrM6xTg==} - '@tanstack/react-query@5.95.2': - resolution: {integrity: sha512-/wGkvLj/st5Ud1Q76KF1uFxScV7WeqN1slQx5280ycwAyYkIPGaRZAEgHxe3bjirSd5Zpwkj6zNcR4cqYni/ZA==} + '@tanstack/react-query@5.101.2': + resolution: {integrity: sha512-seDkr6kzGzX1okaaTtZPtgA688CDPlXUz1C6xSg0ESqn04Vuc8tlrYms1s3de+znBqhPVxFRfpAfUf+6XvfPWg==} peerDependencies: react: ^18 || ^19 - '@tanstack/react-virtual@3.13.23': - resolution: {integrity: sha512-XnMRnHQ23piOVj2bzJqHrRrLg4r+F86fuBcwteKfbIjJrtGxb4z7tIvPVAe4B+4UVwo9G4Giuz5fmapcrnZ0OQ==} + '@tanstack/react-virtual@3.14.5': + resolution: {integrity: sha512-4EKRXh7zBLkbKbFmG3AUVkircuHd+7OdT1pocJSepxtfBd3qnrJgJ5rtPkRYyo9fmyVb2+pI2xPy5oYvMLQy6A==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/virtual-core@3.13.23': - resolution: {integrity: sha512-zSz2Z2HNyLjCplANTDyl3BcdQJc2k1+yyFoKhNRmCr7V7dY8o8q5m8uFTI1/Pg1kL+Hgrz6u3Xo6eFUB7l66cg==} + '@tanstack/virtual-core@3.17.3': + resolution: {integrity: sha512-8Np/TFELpI0ySuJoVmjvOrQYXH/8sTX0Biv9szhFhY39xOdAAY+smrMxjxOum/ux3eM8MUJQsEJ0/R0UpvC8dw==} '@tsconfig/node-ts@23.6.4': resolution: {integrity: sha512-37BMJvNQZ+vTgd1xG2TGBkJ6ENeT4eO4Wh2CHrnn0IwH7ybLFCzh4Uc//kc7UIvqiRac4uGdIc1meKOjMSlKzw==} @@ -3218,6 +2977,9 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} @@ -3227,12 +2989,18 @@ packages: '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/esrecurse@4.3.1': resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -3251,9 +3019,6 @@ packages: '@types/node@22.7.5': resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} - '@types/node@25.3.3': - resolution: {integrity: sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==} - '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} @@ -3451,37 +3216,34 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - '@vitest/expect@3.1.4': - resolution: {integrity: sha512-xkD/ljeliyaClDYqHPNCiJ0plY5YIcM0OlRiZizLhlPmpXWpxnGMyTZXOHFhFeG7w9P5PBeL4IdtJ/HeQwTbQA==} + '@vitest/expect@3.2.7': + resolution: {integrity: sha512-E8eBXaKibuvH2pSZErOjdVb5vF4PbKYcrnluBTYxEk1l/VhhwZg1kZQsdtjq+CsF5CFydf2Rdkz7jDHKSisi3w==} - '@vitest/mocker@3.1.4': - resolution: {integrity: sha512-8IJ3CvwtSw/EFXqWFL8aCMu+YyYXG2WUSrQbViOZkWTKTVicVwZ/YiEZDSqD00kX+v/+W+OnxhNWoeVKorHygA==} + '@vitest/mocker@3.2.7': + resolution: {integrity: sha512-Trr0hYO9CM3Wj6ksWHRhK9IZpIY6wTMO5u/MqXurMxT57sWBaOPEtP3Oq60ihZuh5JsiagKfz95OcxdEP6dBrA==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.1.4': - resolution: {integrity: sha512-cqv9H9GvAEoTaoq+cYqUTCGscUjKqlJZC7PRwY5FMySVj5J+xOm1KQcCiYHJOEzOKRUhLH4R2pTwvFlWCEScsg==} - - '@vitest/pretty-format@3.2.4': - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + '@vitest/pretty-format@3.2.7': + resolution: {integrity: sha512-KUHlwqVu0sRlhCdyPdQ/wBoTfRahjUky1MubOmYw9fWfIZy1gNoHpuaaQBPAaMaVYdQYHJLurzj8ECCj5OwTqA==} - '@vitest/runner@3.1.4': - resolution: {integrity: sha512-djTeF1/vt985I/wpKVFBMWUlk/I7mb5hmD5oP8K9ACRmVXgKTae3TUOtXAEBfslNKPzUQvnKhNd34nnRSYgLNQ==} + '@vitest/runner@3.2.7': + resolution: {integrity: sha512-sB9y4ovltoQP+WaUPwmSxO9WIg9Ig694Di5PalVPsYHklAdE027mehpWF2SQSVq+k6sFgaivbTjTJwZLSHbedA==} - '@vitest/snapshot@3.1.4': - resolution: {integrity: sha512-JPHf68DvuO7vilmvwdPr9TS0SuuIzHvxeaCkxYcCD4jTk67XwL45ZhEHFKIuCm8CYstgI6LZ4XbwD6ANrwMpFg==} + '@vitest/snapshot@3.2.7': + resolution: {integrity: sha512-7C+MwShwtBSI5Buwoyg3s/iY1eHL9PKAf+O1wVh/TdnjXUtkoL/9YQtre90i4MtNXM6edP1wJ2zOBpfCyhIS7g==} - '@vitest/spy@3.1.4': - resolution: {integrity: sha512-Xg1bXhu+vtPXIodYN369M86K8shGLouNjoVI78g8iAq2rFoHFdajNvJJ5A/9bPMFcfQqdaCpOgWKEoMQg/s0Yg==} + '@vitest/spy@3.2.7': + resolution: {integrity: sha512-Q2eQGI6d2L/hBtZ0qNuKcAGid68XK6cv1xsoaIma6PaJhHPoqcEJhYpXZ/5myCMqkNgtP6UKuBhbc0nHKnrkuQ==} - '@vitest/utils@3.1.4': - resolution: {integrity: sha512-yriMuO1cfFhmiGc8ataN51+9ooHRuURdfAZfwFd3usWynjzpLslZdYnRegTv32qdgtJTsj15FoeZe2g15fY1gg==} + '@vitest/utils@3.2.7': + resolution: {integrity: sha512-x6BDOd7dyo3PFLY3I9/HJ25X/6OurhGXk2/B9gOZNPF7XDVjeBK4k01lQE5uvDpbuheErh91qYuE1E2OEjK3Rw==} '@wagmi/connectors@6.2.0': resolution: {integrity: sha512-2NfkbqhNWdjfibb4abRMrn7u6rPjEGolMfApXss6HCDVt9AW2oVC6k8Q5FouzpJezElxLJSagWz9FW1zaRlanA==} @@ -3505,21 +3267,21 @@ packages: typescript: optional: true - '@wallet-standard/app@1.1.0': - resolution: {integrity: sha512-3CijvrO9utx598kjr45hTbbeeykQrQfKmSnxeWOgU25TOEpvcipD/bYDQWIqUv1Oc6KK4YStokSMu/FBNecGUQ==} - engines: {node: '>=16'} + '@wallet-standard/app@1.1.1': + resolution: {integrity: sha512-WDGwoByhP5gwHH01r5EaLgQdLVkACPCdOMQhmhn8rsm10h/siSgTorShzBxrn0ExSPof+Lu+C3TfgqBrPa1xoQ==} + engines: {node: '>=22'} - '@wallet-standard/base@1.1.0': - resolution: {integrity: sha512-DJDQhjKmSNVLKWItoKThJS+CsJQjR9AOBOirBVT1F9YpRyC9oYHE+ZnSf8y8bxUphtKqdQMPVQ2mHohYdRvDVQ==} - engines: {node: '>=16'} + '@wallet-standard/base@1.1.1': + resolution: {integrity: sha512-gggIHTtxicF9XFMQ12DkfS6NAG92Ak795JeSA7f2whAQ6Y3AkMWWuCMxSZXG2NIPN42kEaZSNVjqMsJRaJRxMQ==} + engines: {node: '>=22'} - '@wallet-standard/features@1.1.0': - resolution: {integrity: sha512-hiEivWNztx73s+7iLxsuD1sOJ28xtRix58W7Xnz4XzzA/pF0+aicnWgjOdA10doVDEDZdUuZCIIqG96SFNlDUg==} - engines: {node: '>=16'} + '@wallet-standard/features@1.1.1': + resolution: {integrity: sha512-aCWYmVeSCGViyEU5k7GMoW8zxE4Gs+C1s1Pp2XLesvSNlnZ4PMES9HUnTB3hl0b3RVj7C61yze3IWyrncqg4MA==} + engines: {node: '>=22'} - '@wallet-standard/wallet@1.1.0': - resolution: {integrity: sha512-Gt8TnSlDZpAl+RWOOAB/kuvC7RpcdWAlFbHNoi4gsXsfaWa1QCT6LBcfIYTPdOZC9OVZUDwqGuGAcqZejDmHjg==} - engines: {node: '>=16'} + '@wallet-standard/wallet@1.1.1': + resolution: {integrity: sha512-8WiRPaKk/wNNRZhB2eVhpR/JW7/aqTCMoZhgVUCujuzDmxxmGvsosMxdCG4NAdYkoyozAHCX8/xLtlWUn5mNdQ==} + engines: {node: '>=22'} '@walletconnect/core@2.21.0': resolution: {integrity: sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw==} @@ -3626,9 +3388,6 @@ packages: '@x402/fetch@2.5.0': resolution: {integrity: sha512-D2jH3bn0nf8w9Jg3Vxo+6reE6Z9GickzkSIw+udITJFvsrGOpfjZvhcTeflLcthCODk4Nuu9Oe8x7Q3NLUdaRQ==} - '@zeit/schemas@2.36.0': - resolution: {integrity: sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==} - abitype@1.0.6: resolution: {integrity: sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==} peerDependencies: @@ -3678,6 +3437,10 @@ packages: aes-js@4.0.0-beta.5: resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + agentkeepalive@4.6.0: resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} engines: {node: '>= 8.0.0'} @@ -3685,15 +3448,9 @@ packages: ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} - ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} - ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -3725,12 +3482,6 @@ packages: apg-js@4.4.0: resolution: {integrity: sha512-fefmXFknJmtgtNEXfPwZKYkMFX4Fyeyz+fNF6JWp87biGOPslJbCBVU158zvKRZfHBKnJDy8CMM40oLFGkXT8Q==} - arch@2.2.0: - resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} - - arg@5.0.2: - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -3748,10 +3499,6 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - asn1js@3.0.7: - resolution: {integrity: sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==} - engines: {node: '>=12.0.0'} - assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -3782,8 +3529,11 @@ packages: axios@1.13.6: resolution: {integrity: sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==} - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + axios@1.16.0: + resolution: {integrity: sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==} + + axios@1.18.0: + resolution: {integrity: sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==} balanced-match@4.0.4: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} @@ -3813,12 +3563,6 @@ packages: big.js@6.2.2: resolution: {integrity: sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==} - blake3-wasm@2.1.5: - resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} - - blakejs@1.2.1: - resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} - bn.js@4.12.3: resolution: {integrity: sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==} @@ -3831,13 +3575,6 @@ packages: bowser@2.14.1: resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} - boxen@7.0.0: - resolution: {integrity: sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==} - engines: {node: '>=14.16'} - - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@5.0.4: resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} engines: {node: 18 || 20 || >=22} @@ -3877,18 +3614,6 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} - bytes@3.0.0: - resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} - engines: {node: '>= 0.8'} - - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - - bytestreamjs@2.0.1: - resolution: {integrity: sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==} - engines: {node: '>=6.0.0'} - cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -3897,8 +3622,8 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} engines: {node: '>= 0.4'} call-bound@1.0.4: @@ -3913,33 +3638,17 @@ packages: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} - camelcase@7.0.1: - resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} - engines: {node: '>=14.16'} - caniuse-lite@1.0.30001775: resolution: {integrity: sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==} - cbor2@1.12.0: - resolution: {integrity: sha512-3Cco8XQhi27DogSp9Ri6LYNZLi/TBY/JVnDe+mj06NkBjW/ZYOtekaEU4wZ4xcRMNrFkDv8KNtOAqHyDfz3lYg==} - engines: {node: '>=18.7'} - chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} - chalk-template@0.4.0: - resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==} - engines: {node: '>=12'} - chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.0.1: - resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - chalk@5.6.2: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} @@ -3985,10 +3694,6 @@ packages: resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} engines: {node: '>=20'} - clipboardy@3.0.0: - resolution: {integrity: sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} @@ -3996,10 +3701,6 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} - cliui@9.0.1: - resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} - engines: {node: '>=20'} - clsx@1.2.1: resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} engines: {node: '>=6'} @@ -4047,26 +3748,11 @@ packages: compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} - compressible@2.0.18: - resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} - engines: {node: '>= 0.6'} - - compression@1.8.1: - resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==} - engines: {node: '>= 0.8.0'} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - concurrently@9.2.1: resolution: {integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==} engines: {node: '>=18'} hasBin: true - content-disposition@0.5.2: - resolution: {integrity: sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==} - engines: {node: '>= 0.6'} - conventional-changelog-angular@8.2.0: resolution: {integrity: sha512-4YB1zEXqB17oBI8yRsAs1T+ZhbdsOgJqkl6Trz+GXt/eKf1e4jnA0oW+sOd9BEENzEViuNW0DNoFFjSf3CeC5Q==} engines: {node: '>=18'} @@ -4091,12 +3777,8 @@ packages: resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - cookie-es@1.2.2: - resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} - - cookie@1.1.1: - resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} - engines: {node: '>=18'} + cookie-es@1.2.3: + resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -4153,14 +3835,6 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -4191,10 +3865,6 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -4214,8 +3884,8 @@ packages: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} - defu@6.1.4: - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} delay@5.0.0: resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} @@ -4240,6 +3910,11 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -4262,10 +3937,6 @@ packages: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} - dotenv@17.3.1: - resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} - engines: {node: '>=12'} - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -4273,9 +3944,6 @@ packages: duplexify@4.1.3: resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - eciesjs@0.4.18: resolution: {integrity: sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ==} engines: {bun: '>=1', deno: '>=2', node: '>=16'} @@ -4292,27 +3960,21 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - encode-utf8@1.0.3: resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} - encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - engine.io-client@6.6.4: - resolution: {integrity: sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==} + engine.io-client@6.6.6: + resolution: {integrity: sha512-iY6QdftLQ9pyiPoX082bpf/u1UewnOaJrtJIF9T0++QB34lZrj0uP+Q/bj8AlUsAxqhnkTV2BS8SBZSxOmoV5Q==} engine.io-parser@5.2.3: resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} engines: {node: '>=10.0.0'} - enhanced-resolve@5.20.0: - resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} + enhanced-resolve@5.21.6: + resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} engines: {node: '>=10.13.0'} enquirer@2.4.1: @@ -4330,9 +3992,6 @@ packages: error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} - error-stack-parser-es@1.0.5: - resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} - es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -4519,12 +4178,8 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - expect-type@1.3.0: - resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} extendable-error@0.1.7: @@ -4612,6 +4267,15 @@ packages: debug: optional: true + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + for-each@0.3.5: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} @@ -4620,8 +4284,8 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} - framer-motion@12.38.0: - resolution: {integrity: sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==} + framer-motion@12.42.2: + resolution: {integrity: sha512-5XY9luDiu0oHfHBjpDthFMh0ES+122w6p/papSJBweMkO8Sn+PW2QaEgRblQBpWFnuvZS5qvarpt/hO2pjGmnw==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -4650,8 +4314,8 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - fuse.js@7.1.0: - resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==} + fuse.js@7.4.2: + resolution: {integrity: sha512-LVbzjD4WA6UP5B1UnP8wuaXJiLnqMdM/E4fiJXTJ5haJ5b/MBNsK29h2fm6swEoQaVQjvYFWKLE2RanyZIoRVQ==} engines: {node: '>=10'} generator-function@2.0.1: @@ -4682,10 +4346,6 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - get-tsconfig@4.13.6: resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} @@ -4722,8 +4382,8 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - h3@1.15.10: - resolution: {integrity: sha512-YzJeWSkDZxAhvmp8dexjRK5hxziRO7I9m0N53WhvYL5NiWfkUkzssVzY9jvGu0HBoLFW6+duYmNSn6MaZBCCtg==} + h3@1.15.11: + resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==} has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} @@ -4750,18 +4410,18 @@ packages: hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - hono@4.12.9: - resolution: {integrity: sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA==} + hono@4.12.27: + resolution: {integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==} engines: {node: '>=16.9.0'} + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + human-id@4.1.3: resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} hasBin: true - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} @@ -4770,10 +4430,6 @@ packages: engines: {node: '>=18'} hasBin: true - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - iconv-lite@0.7.2: resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} @@ -4781,15 +4437,12 @@ packages: idb-keyval@6.2.1: resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} - idb-keyval@6.2.2: - resolution: {integrity: sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==} + idb-keyval@6.2.6: + resolution: {integrity: sha512-FY64UEhw+5liMzMQ1R9Mw6AF0+wyBrg1CIA1z4CjI/EvT5ty/SvQcWZgd8s9sgaNhX10Y8UzScTh89tEAls5nA==} idb@7.1.1: resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} - idb@8.0.3: - resolution: {integrity: sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==} - ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -4819,9 +4472,6 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - ini@4.1.1: resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -4866,11 +4516,6 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4922,10 +4567,6 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} - is-port-reachable@4.0.0: - resolution: {integrity: sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -4950,10 +4591,6 @@ packages: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - is-wsl@3.1.1: resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} engines: {node: '>=16'} @@ -4991,8 +4628,12 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true - jose@6.2.2: - resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + jose@6.2.3: + resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} js-base64@3.7.8: resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==} @@ -5003,6 +4644,9 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + js-yaml@3.14.2: resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true @@ -5022,9 +4666,6 @@ packages: json-canonicalize@1.2.0: resolution: {integrity: sha512-TTdjBvqrqJKSADlEsY5rWbx8/1tOrVlTR/aSLU8N2VSInCTffP0p+byYB8Es+OmL4ZOeEftjUdvV+eJeSzJC/Q==} - json-canonicalize@2.0.0: - resolution: {integrity: sha512-yyrnK/mEm6Na3ChbJUWueXdapueW0p380RUyTW87XGb1ww8l8hU0pRrGC3vSWHe9CxrbPHX2fGUOZpNiHR0IIg==} - json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} @@ -5069,81 +4710,40 @@ packages: keyvaluestorage-interface@1.0.0: resolution: {integrity: sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==} - kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lightningcss-android-arm64@1.31.1: - resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [android] - lightningcss-android-arm64@1.32.0: resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] - lightningcss-darwin-arm64@1.31.1: - resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [darwin] - lightningcss-darwin-arm64@1.32.0: resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.31.1: - resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [darwin] - lightningcss-darwin-x64@1.32.0: resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.31.1: - resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [freebsd] - lightningcss-freebsd-x64@1.32.0: resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.31.1: - resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} - engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] - lightningcss-linux-arm-gnueabihf@1.32.0: resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.31.1: - resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [glibc] - lightningcss-linux-arm64-gnu@1.32.0: resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} engines: {node: '>= 12.0.0'} @@ -5151,13 +4751,6 @@ packages: os: [linux] libc: [glibc] - lightningcss-linux-arm64-musl@1.31.1: - resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [musl] - lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} @@ -5165,13 +4758,6 @@ packages: os: [linux] libc: [musl] - lightningcss-linux-x64-gnu@1.31.1: - resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [glibc] - lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} @@ -5179,13 +4765,6 @@ packages: os: [linux] libc: [glibc] - lightningcss-linux-x64-musl@1.31.1: - resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [musl] - lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} @@ -5193,34 +4772,18 @@ packages: os: [linux] libc: [musl] - lightningcss-win32-arm64-msvc@1.31.1: - resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] - lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.31.1: - resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [win32] - lightningcss-win32-x64-msvc@1.32.0: resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.31.1: - resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==} - engines: {node: '>= 12.0.0'} - lightningcss@1.32.0: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} @@ -5240,8 +4803,8 @@ packages: lit-element@4.2.2: resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} - lit-html@3.3.2: - resolution: {integrity: sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==} + lit-html@3.3.3: + resolution: {integrity: sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==} lit@3.3.0: resolution: {integrity: sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==} @@ -5272,8 +4835,8 @@ packages: lodash.upperfirst@4.3.1: resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} - lodash@4.17.23: - resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} log-update@6.1.0: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} @@ -5286,8 +4849,8 @@ packages: loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - lru-cache@11.2.7: - resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==} + lru-cache@11.5.1: + resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -5321,9 +4884,6 @@ packages: resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} engines: {node: '>=18'} - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -5335,22 +4895,10 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mime-db@1.33.0: - resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==} - engines: {node: '>= 0.6'} - mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - mime-db@1.54.0: - resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} - engines: {node: '>= 0.6'} - - mime-types@2.1.18: - resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==} - engines: {node: '>= 0.6'} - mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} @@ -5363,11 +4911,6 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} - miniflare@4.20260305.0: - resolution: {integrity: sha512-jVhtKJtiwaZa3rI+WgoLvSJmEazDsoUmAPYRUmEe2VO6VSbvkhbnDRm+dsPbYRatgNIExwrpqG1rv96jHiSb0w==} - engines: {node: '>=18.0.0'} - hasBin: true - minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -5378,9 +4921,6 @@ packages: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -5392,11 +4932,11 @@ packages: typescript: optional: true - motion-dom@12.38.0: - resolution: {integrity: sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==} + motion-dom@12.42.2: + resolution: {integrity: sha512-5gIMWLp/PycBtJRJWRgjxke5n8dlvkSn2DrYW+tr3XcqAZY1xZh6BJyooJXCM8wdfM7wfMjkBJNLge1CKPUIRA==} - motion-utils@12.36.0: - resolution: {integrity: sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==} + motion-utils@12.39.0: + resolution: {integrity: sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==} motion@12.34.0: resolution: {integrity: sha512-01Sfa/zgsD/di8zA/uFW5Eb7/SPXoGyUfy+uMRMW5Spa8j0z/UbfQewAYvPMYFCXRlyD6e5aLHh76TxeeJD+RA==} @@ -5416,9 +4956,6 @@ packages: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} - ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -5445,10 +4982,6 @@ packages: resolution: {integrity: sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==} engines: {node: '>=18'} - negotiator@0.6.4: - resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} - engines: {node: '>= 0.6'} - node-addon-api@2.0.2: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} @@ -5481,10 +5014,6 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - obj-multiplex@1.0.0: resolution: {integrity: sha512-0GNJAOsHoBHeNTvl5Vt6IWnpUEcc3uSRxzBri7EDyIcMgYvnY2JL2qdeV5zTMjWQX5OHcD5amcW2HFfDh0gjIA==} @@ -5494,10 +5023,6 @@ packages: on-exit-leak-free@0.2.0: resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==} - on-headers@1.1.0: - resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} - engines: {node: '>= 0.8'} - once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -5526,24 +5051,16 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - ox@0.11.3: - resolution: {integrity: sha512-1bWYGk/xZel3xro3l8WGg6eq4YEKlaqvyMtVhfMFpbJzK2F6rj4EDRtqDCWVEJMkzcmEi9uW2QxsqELokOlarw==} + ox@0.13.1: + resolution: {integrity: sha512-S6XU/Chz7HSSlAp7KYZigW8iwSyfS9M+GKTbyDQuZDsqC8S8GUFB2bLBLLB2SfHw8eE2MfymQazVXoLNljLycg==} peerDependencies: typescript: '>=5.4.0' peerDependenciesMeta: typescript: optional: true - ox@0.12.4: - resolution: {integrity: sha512-+P+C7QzuwPV8lu79dOwjBKfB2CbnbEXe/hfyyrff1drrO1nOOj3Hc87svHfcW1yneRr3WXaKr6nz11nq+/DF9Q==} - peerDependencies: - typescript: '>=5.4.0' - peerDependenciesMeta: - typescript: - optional: true - - ox@0.13.1: - resolution: {integrity: sha512-S6XU/Chz7HSSlAp7KYZigW8iwSyfS9M+GKTbyDQuZDsqC8S8GUFB2bLBLLB2SfHw8eE2MfymQazVXoLNljLycg==} + ox@0.14.29: + resolution: {integrity: sha512-M5j87Ec4V99MQdRct/g09eWXW60g6zhHTUs1lr4deUtrPDnezBdCJTgKd7pxqTpSZBFveV0ALi9jMMuT1qKyNg==} peerDependencies: typescript: '>=5.4.0' peerDependenciesMeta: @@ -5621,19 +5138,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-is-inside@1.0.2: - resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-to-regexp@3.3.0: - resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==} - - path-to-regexp@6.3.0: - resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} - path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -5678,10 +5186,6 @@ packages: resolution: {integrity: sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==} hasBin: true - pkijs@3.3.3: - resolution: {integrity: sha512-+KD8hJtqQMYoTuL1bbGOqxb4z+nZkTAwVdNtWwe8Tc2xNbEmdJYIYoc6Qt0uF55e6YW6KuTHw1DjQ18gMhzepw==} - engines: {node: '>=16.0.0'} - pngjs@5.0.0: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} @@ -5733,8 +5237,8 @@ packages: preact@10.24.2: resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} - preact@10.29.0: - resolution: {integrity: sha512-wSAGyk2bYR1c7t3SZ3jHcM6xy0lcBcDel6lODcs9ME6Th++Dx2KU+6D3HD8wMMKGA8Wpw7OMd3/4RGzYRpzwRg==} + preact@10.29.4: + resolution: {integrity: sha512-GMpwh9+NJ8tSmqwIaVyFRQkiKfBEzQ+k7r7tle4W+kaJ+7wJiB9hFz9BixAomMtenPPSBfM4bZhXozGxhf0uFQ==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -5762,6 +5266,10 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} @@ -5769,13 +5277,6 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - pvtsutils@1.3.6: - resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} - - pvutils@1.1.5: - resolution: {integrity: sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==} - engines: {node: '>=16.0.0'} - qrcode@1.5.3: resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} engines: {node: '>=10.13.0'} @@ -5802,16 +5303,8 @@ packages: radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} - range-parser@1.2.0: - resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==} - engines: {node: '>= 0.6'} - - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - - react-apple-signin-auth@1.1.2: - resolution: {integrity: sha512-E5bPu4LtNR3IDsd08A/f1Y0HyuHfjqQpRNRCtQQ3JSVby2JK50FoixyK8EwUh6cbu8N4qrJStL77dEb51Ny5uA==} + react-apple-signin-auth@1.2.1: + resolution: {integrity: sha512-xRX7F28H4y8SyBL0vRP3kXh/aifU0K2lomarWxW/Twxfbhp6Vd56I+cZmmAsEa2AI1CyML84xvedriARju1a/w==} peerDependencies: react: '>= 16.8.0' react-dom: '>= 16.8.0' @@ -5821,8 +5314,8 @@ packages: peerDependencies: react: ^18.3.1 - react-hook-form@7.72.0: - resolution: {integrity: sha512-V4v6jubaf6JAurEaVnT9aUPKFbNtDgohj5CIgVGyPHvT9wRx5OZHVjz31GsxnPNI278XMu+ruFz+wGOscHaLKw==} + react-hook-form@7.81.0: + resolution: {integrity: sha512-ocbmr2p5KBMoAfj4WCUvped33lVi1Kd5DuDUvQDnB6VEAacOjPI/jMbtDdbhco4y9ct4xUuCmMY0b/C9L0QHjw==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -5890,13 +5383,6 @@ packages: resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==} engines: {node: '>= 12.13.0'} - registry-auth-token@3.3.2: - resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} - - registry-url@3.1.0: - resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} - engines: {node: '>=0.10.0'} - require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -5934,13 +5420,13 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rollup@4.59.0: - resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} + rollup@4.62.2: + resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - rpc-websockets@9.3.7: - resolution: {integrity: sha512-dQal1U0yKH2umW0DgqSecP4G1jNxyPUGY60uUMB8bLoXabC2aWT3Cag9hOhZXsH/52QJEcggxNNWhF+Fp48ykw==} + rpc-websockets@9.3.9: + resolution: {integrity: sha512-2iQDaTB4g5fDB2ihrTFSJSibCEuxaRi1q7qTW7ZO9/M5/TC+ToHA4D9/ffNLEbAoHNNrcdeP05oATNk44SKZXA==} run-applescript@7.1.0: resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} @@ -5984,14 +5470,6 @@ packages: engines: {node: '>=10'} hasBin: true - serve-handler@6.1.6: - resolution: {integrity: sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==} - - serve@14.2.5: - resolution: {integrity: sha512-Qn/qMkzCcMFVPb60E/hQy+iRLpiU8PamOfOSYoAHmmF+fFFmpPpqa6Oci2iWYpTdOUM3VF+TINud7CfbQnsZbA==} - engines: {node: '>= 14'} - hasBin: true - set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} @@ -6004,10 +5482,6 @@ packages: engines: {node: '>= 0.10'} hasBin: true - sharp@0.34.5: - resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -6122,10 +5596,6 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - string-width@7.2.0: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} @@ -6152,13 +5622,8 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} superstruct@1.0.4: resolution: {integrity: sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==} @@ -6168,10 +5633,6 @@ packages: resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} engines: {node: '>=14.0.0'} - supports-color@10.2.2: - resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} - engines: {node: '>=18'} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -6180,17 +5641,14 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - tailwind-merge@3.5.0: - resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} + tailwind-merge@3.6.0: + resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} - tailwindcss@4.2.1: - resolution: {integrity: sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==} + tailwindcss@4.3.2: + resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} - tailwindcss@4.2.2: - resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==} - - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} term-size@2.2.1: @@ -6230,8 +5688,8 @@ packages: resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - tinyspy@3.0.2: - resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} to-buffer@1.2.2: @@ -6269,9 +5727,6 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - tweetnacl-sealedbox-js@1.2.0: - resolution: {integrity: sha512-QoCr8K2hwri+ky7SUa22oSre8g88XaWi0hwwWd16pJMuDyn5gL/UyE0PyR2EOFEMJ70T2trJ9+Sv+Qa18olEmQ==} - tweetnacl@1.0.3: resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} @@ -6279,10 +5734,6 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - type-fest@4.41.0: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} @@ -6303,8 +5754,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - ufo@1.6.3: - resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} uint8arrays@3.1.0: resolution: {integrity: sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog==} @@ -6318,22 +5769,8 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.18.2: - resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - - undici-types@7.24.6: - resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} - - undici@7.18.2: - resolution: {integrity: sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==} - engines: {node: '>=20.18.1'} - - undici@7.22.0: - resolution: {integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==} - engines: {node: '>=20.18.1'} - - unenv@2.0.0-rc.24: - resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} + undici-types@7.28.0: + resolution: {integrity: sha512-LJAfY+2w6HGeT8d8J1wNQsUGUEGio6NWWpwdwurQe4f6oojzCFuGLizl1KSve4irsTxyLly1QhEeE6iapdaIvQ==} universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} @@ -6410,9 +5847,6 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - update-check@1.5.4: - resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==} - uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -6462,22 +5896,21 @@ packages: uuid@10.0.0: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true - uuid@11.1.0: - resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} - hasBin: true - - uuid@13.0.0: - resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} + uuid@14.0.1: + resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==} hasBin: true uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true valid-url@1.0.9: @@ -6495,10 +5928,6 @@ packages: react: optional: true - vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - viem@2.23.2: resolution: {integrity: sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==} peerDependencies: @@ -6507,16 +5936,16 @@ packages: typescript: optional: true - viem@2.46.3: - resolution: {integrity: sha512-2LJS+Hyh2sYjHXQtzfv1kU9pZx9dxFzvoU/ZKIcn0FNtOU0HQuIICuYdWtUDFHaGXbAdVo8J1eCvmjkL9JVGwg==} + viem@2.53.1: + resolution: {integrity: sha512-FhfJ/SW73CVosiyVLmIMVgKDRKYV1AGCLzZoHYvmNayyVff63Qi1ocPCk59LqC/cNw244RbBJjHnmxqXkE7NpA==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: typescript: optional: true - vite-node@3.1.4: - resolution: {integrity: sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA==} + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true @@ -6551,16 +5980,16 @@ packages: terser: optional: true - vitest@3.1.4: - resolution: {integrity: sha512-Ta56rT7uWxCSJXlBtKgIlApJnT6e6IGmTYxYcmxjJ4ujuZDI59GUQgVDObXXJujOmPDBYXHK1qmaGtneu6TNIQ==} + vitest@3.2.7: + resolution: {integrity: sha512-KrxIJ62Fd89gfysR4WotlgZABiz2dqFPgqGzX7s+CwsqLFomRH7777ZcrOD6+WVAh7khPQP41A+BKbpcJFrdEg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.1.4 - '@vitest/ui': 3.1.4 + '@vitest/browser': 3.2.7 + '@vitest/ui': 3.2.7 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -6602,8 +6031,8 @@ packages: which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - which-typed-array@1.1.20: - resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + which-typed-array@1.1.22: + resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} engines: {node: '>= 0.4'} which@2.0.2: @@ -6616,10 +6045,6 @@ packages: engines: {node: '>=8'} hasBin: true - widest-line@4.0.1: - resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} - engines: {node: '>=12'} - widest-line@5.0.0: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} @@ -6628,21 +6053,6 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - workerd@1.20260305.0: - resolution: {integrity: sha512-JkhfCLU+w+KbQmZ9k49IcDYc78GBo7eG8Mir8E2+KVjR7otQAmpcLlsous09YLh8WQ3Bt3Mi6/WMStvMAPukeA==} - engines: {node: '>=16'} - hasBin: true - - wrangler@4.69.0: - resolution: {integrity: sha512-EmVfIM65I5b4ITHe3Y9R7zQyf4NUBQ1leStakMlWiVR9n6VlDwuEltyQI2l3i0JciDnWyR3uqe+T6C08ivniTQ==} - engines: {node: '>=20.0.0'} - hasBin: true - peerDependencies: - '@cloudflare/workers-types': ^4.20260305.0 - peerDependenciesMeta: - '@cloudflare/workers-types': - optional: true - wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -6651,10 +6061,6 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -6662,8 +6068,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + ws@7.5.11: + resolution: {integrity: sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==} engines: {node: '>=8.3.0'} peerDependencies: bufferutil: ^4.0.1 @@ -6698,8 +6104,8 @@ packages: utf-8-validate: optional: true - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -6710,8 +6116,20 @@ packages: utf-8-validate: optional: true - ws@8.20.0: - resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + ws@8.20.1: + resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -6757,10 +6175,6 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - yargs-parser@22.0.0: - resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yargs@15.4.1: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} @@ -6769,10 +6183,6 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} - yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -6780,12 +6190,6 @@ packages: yoga-layout@3.2.1: resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} - youch-core@0.3.3: - resolution: {integrity: sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==} - - youch@4.1.0-beta.10: - resolution: {integrity: sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==} - zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} @@ -6813,8 +6217,8 @@ packages: use-sync-external-store: optional: true - zustand@5.0.12: - resolution: {integrity: sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==} + zustand@5.0.14: + resolution: {integrity: sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==} engines: {node: '>=12.20.0'} peerDependencies: '@types/react': '>=18.0.0' @@ -6851,50 +6255,50 @@ packages: snapshots: - 0xsequence@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)): - dependencies: - '@0xsequence/abi': 2.3.43 - '@0xsequence/account': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/api': 2.3.43 - '@0xsequence/auth': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/guard': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/indexer': 2.3.43 - '@0xsequence/metadata': 2.3.43 - '@0xsequence/migration': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/network': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/provider': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/relayer': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/sessions': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/signhub': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/wallet': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + 0xsequence@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)): + dependencies: + '@0xsequence/abi': 2.3.44 + '@0xsequence/account': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/api': 2.3.44 + '@0xsequence/auth': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/guard': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/indexer': 2.3.44 + '@0xsequence/metadata': 2.3.44 + '@0xsequence/migration': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/network': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/provider': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/relayer': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/sessions': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/signhub': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/wallet': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - 0xtrails@0.14.0(88585348c7fe3646803356f2c1f98627): + 0xtrails@0.14.0(0xsequence@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@0xsequence/api@3.0.12)(@0xsequence/network@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@react-oauth/google@0.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(bs58@6.0.0)(bufferutil@4.1.0)(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-apple-signin-auth@1.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76): dependencies: - '@0xsequence/connect': 5.4.8(9f1a99b6daf6e9f1f6915a92724c8d18) - '@0xsequence/hooks': 5.4.9(@0xsequence/api@3.0.0-beta.17)(@0xsequence/indexer@3.0.5)(@0xsequence/metadata@3.0.5)(@0xsequence/network@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@tanstack/react-query@5.95.2(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) - '@0xsequence/indexer': 3.0.5 - '@0xsequence/metadata': 3.0.5 + '@0xsequence/connect': 5.4.8(9524d20f2d229702e245bfce2f88d319) + '@0xsequence/hooks': 5.4.11(@0xsequence/api@3.0.12)(@0xsequence/indexer@3.0.12)(@0xsequence/metadata@3.0.12)(@0xsequence/network@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@tanstack/react-query@5.101.2(react@18.3.1))(react@18.3.1)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + '@0xsequence/indexer': 3.0.12 + '@0xsequence/metadata': 3.0.12 '@0xsequence/wallet-primitives': 3.0.0-beta.19(typescript@5.9.3)(zod@3.25.76) '@0xtrails/api': 0.14.0 '@0xtrails/wallet-registry': 0.2.0 '@databeat/tracker': 0.9.3 '@emotion/is-prop-valid': 1.4.0 - '@meshconnect/web-link-sdk': 3.7.1(bs58@6.0.0)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6) + '@meshconnect/web-link-sdk': 3.7.1(bs58@6.0.0)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@tanstack/query-persist-client-core': 5.95.2 - '@tanstack/react-query': 5.95.2(react@18.3.1) - '@tanstack/react-virtual': 3.13.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/query-persist-client-core': 5.101.2 + '@tanstack/react-query': 5.101.2(react@18.3.1) + '@tanstack/react-virtual': 3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lucide-react: 0.563.0(react@18.3.1) motion: 12.34.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) ox: 0.13.1(typescript@5.9.3)(zod@3.25.76) qrcode: 1.5.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - wagmi: 2.19.5(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + wagmi: 2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76) transitivePeerDependencies: - 0xsequence - '@0xsequence/api' @@ -6908,81 +6312,78 @@ snapshots: - encoding - ethers - react-apple-signin-auth + - supports-color - typescript - utf-8-validate - zod '@0xsequence/abi@2.3.41': {} - '@0xsequence/abi@2.3.43': {} - - '@0xsequence/abi@3.0.0-beta.17': {} + '@0xsequence/abi@2.3.44': {} - '@0xsequence/account@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/account@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/abi': 2.3.43 - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/migration': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/network': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/relayer': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/sessions': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/wallet': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/abi': 2.3.44 + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/migration': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/network': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/relayer': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/sessions': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/wallet': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/api@2.3.43': {} + '@0xsequence/api@2.3.44': {} - '@0xsequence/api@3.0.0-beta.17': {} + '@0xsequence/api@3.0.12': {} - '@0xsequence/auth@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/auth@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/abi': 2.3.43 - '@0xsequence/account': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/api': 2.3.43 - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/abi': 2.3.44 + '@0xsequence/account': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/api': 2.3.44 + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@0xsequence/ethauth': 1.0.0(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/indexer': 2.3.43 - '@0xsequence/metadata': 2.3.43 - '@0xsequence/migration': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/network': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/sessions': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/signhub': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/wallet': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/indexer': 2.3.44 + '@0xsequence/metadata': 2.3.44 + '@0xsequence/migration': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/network': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/sessions': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/signhub': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/wallet': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/builder@3.0.0-beta.17': {} - - '@0xsequence/connect@5.4.8(9f1a99b6daf6e9f1f6915a92724c8d18)': + '@0xsequence/connect@5.4.8(9524d20f2d229702e245bfce2f88d319)': dependencies: - 0xsequence: 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/api': 2.3.43 - '@0xsequence/auth': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + 0xsequence: 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/api': 3.0.12 + '@0xsequence/auth': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/core': 2.3.41(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@0xsequence/design-system': 2.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(motion@12.34.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@0xsequence/ethauth': 1.0.0(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/hooks': 5.4.9(@0xsequence/api@3.0.0-beta.17)(@0xsequence/indexer@3.0.5)(@0xsequence/metadata@3.0.5)(@0xsequence/network@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@tanstack/react-query@5.95.2(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) - '@0xsequence/indexer': 2.3.43 - '@0xsequence/metadata': 2.3.43 - '@0xsequence/network': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/provider': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/waas': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/hooks': 5.4.11(@0xsequence/api@3.0.12)(@0xsequence/indexer@3.0.12)(@0xsequence/metadata@3.0.12)(@0xsequence/network@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@tanstack/react-query@5.101.2(react@18.3.1))(react@18.3.1)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + '@0xsequence/indexer': 2.3.41 + '@0xsequence/metadata': 2.3.44 + '@0xsequence/network': 2.3.41(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/provider': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.41(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/waas': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@databeat/tracker': 0.9.3 '@react-oauth/google': 0.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@tailwindcss/cli': 4.2.2 - '@tanstack/react-query': 5.95.2(react@18.3.1) + '@tailwindcss/cli': 4.3.2 + '@tanstack/react-query': 5.101.2(react@18.3.1) clsx: 2.1.1 ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - fuse.js: 7.1.0 + fuse.js: 7.4.2 motion: 12.34.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 - react-apple-signin-auth: 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-apple-signin-auth: 1.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-dom: 18.3.1(react@18.3.1) - tailwindcss: 4.2.2 + tailwindcss: 4.3.2 uuid: 10.0.0 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - wagmi: 2.19.5(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + wagmi: 2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76) transitivePeerDependencies: - '@emotion/is-prop-valid' - '@types/react' @@ -6994,74 +6395,35 @@ snapshots: '@0xsequence/utils': 2.3.41(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/core@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/core@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/abi': 2.3.43 - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/abi': 2.3.44 + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/dapp-client-cli@0.1.5(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6)': - dependencies: - '@0xsequence/dapp-client': 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - dotenv: 17.3.1 - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - undici: 7.22.0 - yargs: 18.0.0 - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - - '@0xsequence/dapp-client@3.0.0-beta.16(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': - dependencies: - '@0xsequence/guard': 3.0.0-beta.19(typescript@5.9.3)(zod@3.25.76) - '@0xsequence/relayer': 3.0.0-beta.16(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@0xsequence/wallet-core': 3.0.0-beta.16(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@0xsequence/wallet-primitives': 3.0.0-beta.16(typescript@5.9.3)(zod@3.25.76) - ox: 0.9.17(typescript@5.9.3)(zod@3.25.76) - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - - '@0xsequence/dapp-client@3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6)': - dependencies: - '@0xsequence/guard': 3.0.0(typescript@5.9.3)(zod@4.3.6) - '@0xsequence/relayer': 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - '@0xsequence/wallet-core': 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - '@0xsequence/wallet-primitives': 3.0.0-beta.17(typescript@5.9.3)(zod@4.3.6) - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - '@0xsequence/design-system@2.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(motion@12.34.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-aspect-ratio': 1.1.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-checkbox': 1.3.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-progress': 1.1.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-radio-group': 1.3.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-select': 2.2.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.4(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-switch': 1.2.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-tabs': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-toast': 1.2.15(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-aspect-ratio': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-checkbox': 1.3.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-collapsible': 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dialog': 1.1.18(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dropdown-menu': 2.1.19(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-progress': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-radio-group': 1.4.2(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-select': 2.3.2(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.3.0(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-switch': 1.3.2(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-tabs': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toast': 1.2.18(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.2.4(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) class-variance-authority: 0.7.1 clsx: 2.1.1 motion: 12.34.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-hook-form: 7.72.0(react@18.3.1) - tailwind-merge: 3.5.0 + react-hook-form: 7.81.0(react@18.3.1) + tailwind-merge: 3.6.0 transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -7071,70 +6433,39 @@ snapshots: ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) js-base64: 3.7.8 - '@0xsequence/guard@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/guard@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/account': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/signhub': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/account': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/signhub': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/guard@3.0.0(typescript@5.9.3)(zod@3.25.76)': + '@0xsequence/hooks@5.4.11(@0xsequence/api@3.0.12)(@0xsequence/indexer@3.0.12)(@0xsequence/metadata@3.0.12)(@0xsequence/network@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@tanstack/react-query@5.101.2(react@18.3.1))(react@18.3.1)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))': dependencies: - ox: 0.9.17(typescript@5.9.3)(zod@3.25.76) - transitivePeerDependencies: - - typescript - - zod - - '@0xsequence/guard@3.0.0(typescript@5.9.3)(zod@4.3.6)': - dependencies: - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - transitivePeerDependencies: - - typescript - - zod - - '@0xsequence/guard@3.0.0-beta.19(typescript@5.9.3)(zod@3.25.76)': - dependencies: - ox: 0.9.17(typescript@5.9.3)(zod@3.25.76) - transitivePeerDependencies: - - typescript - - zod - - '@0xsequence/hooks@5.4.9(@0xsequence/api@3.0.0-beta.17)(@0xsequence/indexer@3.0.5)(@0xsequence/metadata@3.0.5)(@0xsequence/network@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@tanstack/react-query@5.95.2(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))': - dependencies: - '@0xsequence/api': 3.0.0-beta.17 - '@0xsequence/indexer': 3.0.5 - '@0xsequence/metadata': 3.0.5 - '@0xsequence/network': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@tanstack/react-query': 5.95.2(react@18.3.1) + '@0xsequence/api': 3.0.12 + '@0xsequence/indexer': 3.0.12 + '@0xsequence/metadata': 3.0.12 + '@0xsequence/network': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@tanstack/react-query': 5.101.2(react@18.3.1) react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - - '@0xsequence/identity-instrument@3.0.0-beta.19(typescript@5.9.3)(zod@4.3.6)': - dependencies: - json-canonicalize: 2.0.0 - jwt-decode: 4.0.0 - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - transitivePeerDependencies: - - typescript - - zod + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) '@0xsequence/indexer@2.3.41': {} - '@0xsequence/indexer@2.3.43': {} + '@0xsequence/indexer@2.3.44': {} - '@0xsequence/indexer@3.0.5': {} + '@0xsequence/indexer@3.0.12': {} - '@0xsequence/metadata@2.3.43': {} + '@0xsequence/metadata@2.3.44': {} - '@0xsequence/metadata@3.0.5': {} + '@0xsequence/metadata@3.0.12': {} - '@0xsequence/migration@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/migration@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/abi': 2.3.43 - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/wallet': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/abi': 2.3.44 + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/wallet': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@0xsequence/network@2.3.41(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': @@ -7145,25 +6476,25 @@ snapshots: '@0xsequence/utils': 2.3.41(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/network@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/network@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/indexer': 2.3.43 - '@0xsequence/relayer': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/indexer': 2.3.44 + '@0xsequence/relayer': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/provider@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': - dependencies: - '@0xsequence/abi': 2.3.43 - '@0xsequence/account': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/auth': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/migration': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/network': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/relayer': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/wallet': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/provider@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + '@0xsequence/abi': 2.3.44 + '@0xsequence/account': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/auth': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/migration': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/network': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/relayer': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/wallet': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@databeat/tracker': 0.9.3 ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) eventemitter2: 6.4.9 @@ -7176,122 +6507,53 @@ snapshots: '@0xsequence/utils': 2.3.41(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/relayer@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/relayer@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/abi': 2.3.43 - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/abi': 2.3.44 + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/relayer@3.0.0-beta.16(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': - dependencies: - '@0xsequence/wallet-primitives': 3.0.0-beta.17(typescript@5.9.3)(zod@3.25.76) - mipd: 0.0.7(typescript@5.9.3) - ox: 0.9.17(typescript@5.9.3)(zod@3.25.76) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - - '@0xsequence/relayer@3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': - dependencies: - '@0xsequence/wallet-primitives': 3.0.0-beta.17(typescript@5.9.3)(zod@3.25.76) - mipd: 0.0.7(typescript@5.9.3) - ox: 0.9.17(typescript@5.9.3)(zod@3.25.76) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - - '@0xsequence/relayer@3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6)': - dependencies: - '@0xsequence/wallet-primitives': 3.0.0-beta.17(typescript@5.9.3)(zod@4.3.6) - mipd: 0.0.7(typescript@5.9.3) - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - - '@0xsequence/replacer@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/replacer@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/abi': 2.3.43 - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/abi': 2.3.44 + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/sessions@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/sessions@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/migration': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/replacer': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/migration': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/replacer': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) idb: 7.1.1 - '@0xsequence/signhub@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/signhub@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@0xsequence/tee-verifier@0.1.2': - dependencies: - cbor2: 1.12.0 - pkijs: 3.3.3 - '@0xsequence/utils@2.3.41(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) js-base64: 3.7.8 - '@0xsequence/utils@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/utils@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) js-base64: 3.7.8 - '@0xsequence/waas@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@0xsequence/waas@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/network': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/network': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) idb: 7.1.1 json-canonicalize: 1.2.0 jwt-decode: 4.0.0 - '@0xsequence/wallet-core@3.0.0-beta.16(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': - dependencies: - '@0xsequence/guard': 3.0.0(typescript@5.9.3)(zod@3.25.76) - '@0xsequence/relayer': 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@0xsequence/wallet-primitives': 3.0.0-beta.17(typescript@5.9.3)(zod@3.25.76) - mipd: 0.0.7(typescript@5.9.3) - ox: 0.9.17(typescript@5.9.3)(zod@3.25.76) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - - '@0xsequence/wallet-core@3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6)': - dependencies: - '@0xsequence/guard': 3.0.0(typescript@5.9.3)(zod@4.3.6) - '@0xsequence/relayer': 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - '@0xsequence/wallet-primitives': 3.0.0-beta.17(typescript@5.9.3)(zod@4.3.6) - mipd: 0.0.7(typescript@5.9.3) - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - '@0xsequence/wallet-primitives@3.0.0-beta.16(typescript@5.9.3)(zod@3.25.76)': dependencies: ox: 0.9.17(typescript@5.9.3)(zod@3.25.76) @@ -7299,20 +6561,6 @@ snapshots: - typescript - zod - '@0xsequence/wallet-primitives@3.0.0-beta.17(typescript@5.9.3)(zod@3.25.76)': - dependencies: - ox: 0.9.17(typescript@5.9.3)(zod@3.25.76) - transitivePeerDependencies: - - typescript - - zod - - '@0xsequence/wallet-primitives@3.0.0-beta.17(typescript@5.9.3)(zod@4.3.6)': - dependencies: - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - transitivePeerDependencies: - - typescript - - zod - '@0xsequence/wallet-primitives@3.0.0-beta.19(typescript@5.9.3)(zod@3.25.76)': dependencies: ox: 0.9.17(typescript@5.9.3)(zod@3.25.76) @@ -7320,32 +6568,14 @@ snapshots: - typescript - zod - '@0xsequence/wallet-wdk@3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6)': + '@0xsequence/wallet@2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@0xsequence/guard': 3.0.0(typescript@5.9.3)(zod@4.3.6) - '@0xsequence/identity-instrument': 3.0.0-beta.19(typescript@5.9.3)(zod@4.3.6) - '@0xsequence/relayer': 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - '@0xsequence/tee-verifier': 0.1.2 - '@0xsequence/wallet-core': 3.0.0-beta.17(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) - '@0xsequence/wallet-primitives': 3.0.0-beta.17(typescript@5.9.3)(zod@4.3.6) - idb: 8.0.3 - jwt-decode: 4.0.0 - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - uuid: 13.0.0 - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - - '@0xsequence/wallet@2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': - dependencies: - '@0xsequence/abi': 2.3.43 - '@0xsequence/core': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/network': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/relayer': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/signhub': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@0xsequence/utils': 2.3.43(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/abi': 2.3.44 + '@0xsequence/core': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/network': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/relayer': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/signhub': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@0xsequence/utils': 2.3.44(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@0xtrails/api@0.10.4': {} @@ -7369,19 +6599,25 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.29.0': {} + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} - '@babel/core@7.29.0': + '@babel/core@7.29.7': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.28.6 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -7391,83 +6627,91 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.1': + '@babel/generator@7.29.7': dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-compilation-targets@7.28.6': + '@babel/helper-compilation-targets@7.29.7': dependencies: - '@babel/compat-data': 7.29.0 - '@babel/helper-validator-option': 7.27.1 + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 browserslist: 4.28.1 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-globals@7.28.0': {} + '@babel/helper-globals@7.29.7': {} - '@babel/helper-module-imports@7.28.6': + '@babel/helper-module-imports@7.29.7': dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.28.6': {} + '@babel/helper-plugin-utils@7.29.7': {} '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-string-parser@7.29.7': {} + '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helper-validator-option@7.27.1': {} + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} - '@babel/helpers@7.28.6': + '@babel/helpers@7.29.7': dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 - '@babel/parser@7.29.0': + '@babel/parser@7.24.1': dependencies: '@babel/types': 7.29.0 - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 '@babel/runtime@7.29.2': {} - '@babel/template@7.28.6': + '@babel/template@7.29.7': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 - '@babel/traverse@7.29.0': + '@babel/traverse@7.29.7': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -7477,22 +6721,26 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@base-org/account@2.4.0(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(utf-8-validate@6.0.6)(zod@3.25.76)': + '@babel/types@7.29.7': dependencies: - '@coinbase/cdp-sdk': 1.45.0(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6) + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@base-org/account@2.4.0(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(utf-8-validate@6.0.6)(zod@3.25.76)': + dependencies: + '@coinbase/cdp-sdk': 1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) '@noble/hashes': 1.8.0 clsx: 1.2.1 eventemitter3: 5.0.1 idb-keyval: 6.2.1 ox: 0.6.9(typescript@5.9.3)(zod@3.25.76) preact: 10.24.2 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zustand: 5.0.3(@types/react@18.3.28)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)) transitivePeerDependencies: - '@types/react' - bufferutil - debug - - encoding - fastestsmallesttextencoderdecoder - immer - react @@ -7644,49 +6892,25 @@ snapshots: human-id: 4.1.3 prettier: 2.8.8 - '@cloudflare/kv-asset-handler@0.4.2': {} - - '@cloudflare/unenv-preset@2.14.0(unenv@2.0.0-rc.24)(workerd@1.20260305.0)': - dependencies: - unenv: 2.0.0-rc.24 - optionalDependencies: - workerd: 1.20260305.0 - - '@cloudflare/workerd-darwin-64@1.20260305.0': - optional: true - - '@cloudflare/workerd-darwin-arm64@1.20260305.0': - optional: true - - '@cloudflare/workerd-linux-64@1.20260305.0': - optional: true - - '@cloudflare/workerd-linux-arm64@1.20260305.0': - optional: true - - '@cloudflare/workerd-windows-64@1.20260305.0': - optional: true - '@cloudflare/workers-types@4.20260317.1': {} - '@coinbase/cdp-sdk@1.45.0(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@coinbase/cdp-sdk@1.51.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: '@solana-program/system': 0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) '@solana-program/token': 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) '@solana/kit': 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6) abitype: 1.0.6(typescript@5.9.3)(zod@3.25.76) - axios: 1.13.6 - axios-retry: 4.5.0(axios@1.13.6) - jose: 6.2.2 + axios: 1.16.0 + axios-retry: 4.5.0(axios@1.16.0) + bs58: 6.0.0 + jose: 6.2.3 md5: 2.3.0 uncrypto: 0.1.3 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zod: 3.25.76 transitivePeerDependencies: - bufferutil - debug - - encoding - fastestsmallesttextencoderdecoder - typescript - utf-8-validate @@ -7700,7 +6924,7 @@ snapshots: eth-json-rpc-filters: 6.0.1 eventemitter3: 5.0.1 keccak: 3.0.4 - preact: 10.29.0 + preact: 10.29.4 sha.js: 2.4.12 transitivePeerDependencies: - supports-color @@ -7713,7 +6937,7 @@ snapshots: idb-keyval: 6.2.1 ox: 0.6.9(typescript@5.9.3)(zod@3.25.76) preact: 10.24.2 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zustand: 5.0.3(@types/react@18.3.28)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)) transitivePeerDependencies: - '@types/react' @@ -7844,15 +7068,11 @@ snapshots: conventional-commits-parser: 6.3.0 picocolors: 1.1.1 - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - '@databeat/tracker@0.9.3': dependencies: '@noble/hashes': 1.8.0 - '@ecies/ciphers@0.2.5(@noble/ciphers@1.3.0)': + '@ecies/ciphers@0.2.6(@noble/ciphers@1.3.0)': dependencies: '@noble/ciphers': 1.3.0 @@ -8103,9 +7323,9 @@ snapshots: '@esbuild/win32-x64@0.28.0': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.0.3(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.0.3(jiti@2.7.0))': dependencies: - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.0.3(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -8425,11 +7645,11 @@ snapshots: '@floating-ui/utils@0.2.11': {} - '@gemini-wallet/core@0.3.2(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))': + '@gemini-wallet/core@0.3.2(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))': dependencies: '@metamask/rpc-errors': 7.0.2 eventemitter3: 5.0.1 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) transitivePeerDependencies: - supports-color @@ -8444,102 +7664,6 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@img/colour@1.1.0': {} - - '@img/sharp-darwin-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.2.4 - optional: true - - '@img/sharp-darwin-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.2.4 - optional: true - - '@img/sharp-libvips-darwin-arm64@1.2.4': - optional: true - - '@img/sharp-libvips-darwin-x64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-arm64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-arm@1.2.4': - optional: true - - '@img/sharp-libvips-linux-ppc64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-riscv64@1.2.4': - optional: true - - '@img/sharp-libvips-linux-s390x@1.2.4': - optional: true - - '@img/sharp-libvips-linux-x64@1.2.4': - optional: true - - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - optional: true - - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - optional: true - - '@img/sharp-linux-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.2.4 - optional: true - - '@img/sharp-linux-arm@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.2.4 - optional: true - - '@img/sharp-linux-ppc64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.2.4 - optional: true - - '@img/sharp-linux-riscv64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-riscv64': 1.2.4 - optional: true - - '@img/sharp-linux-s390x@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.2.4 - optional: true - - '@img/sharp-linux-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.2.4 - optional: true - - '@img/sharp-linuxmusl-arm64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - optional: true - - '@img/sharp-linuxmusl-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - optional: true - - '@img/sharp-wasm32@0.34.5': - dependencies: - '@emnapi/runtime': 1.8.1 - optional: true - - '@img/sharp-win32-arm64@0.34.5': - optional: true - - '@img/sharp-win32-ia32@0.34.5': - optional: true - - '@img/sharp-win32-x64@0.34.5': - optional: true - '@inquirer/external-editor@1.0.3(@types/node@22.19.13)': dependencies: chardet: 2.1.1 @@ -8572,16 +7696,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping@0.3.9': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@lit-labs/ssr-dom-shim@1.5.1': {} + '@lit-labs/ssr-dom-shim@1.6.0': {} '@lit/reactive-element@2.1.2': dependencies: - '@lit-labs/ssr-dom-shim': 1.5.1 + '@lit-labs/ssr-dom-shim': 1.6.0 '@manypkg/find-root@1.1.0': dependencies: @@ -8599,19 +7718,20 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 - '@meshconnect/node-api@2.0.24': + '@meshconnect/node-api@2.0.27': dependencies: - axios: 1.13.6 + axios: 1.18.0 transitivePeerDependencies: - debug + - supports-color - '@meshconnect/uwc-bridge-parent@1.1.1(bs58@6.0.0)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@meshconnect/uwc-bridge-parent@1.1.1(bs58@6.0.0)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: - '@solana/wallet-adapter-base': 0.9.27(@solana/web3.js@1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@solana/wallet-standard-wallet-adapter-base': 1.1.4(@solana/web3.js@1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6))(bs58@6.0.0) - '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@wallet-standard/app': 1.1.0 - '@wallet-standard/base': 1.1.0 + '@solana/wallet-adapter-base': 0.9.27(@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) + '@solana/wallet-standard-wallet-adapter-base': 1.1.5(@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6))(bs58@6.0.0) + '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + '@wallet-standard/app': 1.1.1 + '@wallet-standard/base': 1.1.1 comlink: 4.4.2 transitivePeerDependencies: - bs58 @@ -8620,15 +7740,16 @@ snapshots: - typescript - utf-8-validate - '@meshconnect/web-link-sdk@3.7.1(bs58@6.0.0)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@meshconnect/web-link-sdk@3.7.1(bs58@6.0.0)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: - '@meshconnect/node-api': 2.0.24 - '@meshconnect/uwc-bridge-parent': 1.1.1(bs58@6.0.0)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6) + '@meshconnect/node-api': 2.0.27 + '@meshconnect/uwc-bridge-parent': 1.1.1(bs58@6.0.0)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) transitivePeerDependencies: - bs58 - bufferutil - debug - encoding + - supports-color - typescript - utf-8-validate @@ -8700,7 +7821,7 @@ snapshots: '@metamask/rpc-errors@7.0.2': dependencies: - '@metamask/utils': 11.10.0 + '@metamask/utils': 11.11.0 fast-safe-stringify: 2.1.1 transitivePeerDependencies: - supports-color @@ -8713,11 +7834,11 @@ snapshots: dependencies: openapi-fetch: 0.13.8 - '@metamask/sdk-communication-layer@0.33.1(cross-fetch@4.1.0(encoding@0.1.13))(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@metamask/sdk-communication-layer@0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@metamask/sdk-analytics': 0.0.5 bufferutil: 4.1.0 - cross-fetch: 4.1.0(encoding@0.1.13) + cross-fetch: 4.1.0 date-fns: 2.30.0 debug: 4.3.4 eciesjs: 0.4.18 @@ -8733,17 +7854,17 @@ snapshots: dependencies: '@paulmillr/qr': 0.2.1 - '@metamask/sdk@0.33.1(bufferutil@4.1.0)(encoding@0.1.13)(utf-8-validate@6.0.6)': + '@metamask/sdk@0.33.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)': dependencies: '@babel/runtime': 7.29.2 '@metamask/onboarding': 1.0.1 '@metamask/providers': 16.1.0 '@metamask/sdk-analytics': 0.0.5 - '@metamask/sdk-communication-layer': 0.33.1(cross-fetch@4.1.0(encoding@0.1.13))(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@metamask/sdk-communication-layer': 0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.18)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@metamask/sdk-install-modal-web': 0.32.1 '@paulmillr/qr': 0.2.1 bowser: 2.14.1 - cross-fetch: 4.1.0(encoding@0.1.13) + cross-fetch: 4.1.0 debug: 4.3.4 eciesjs: 0.4.18 eth-rpc-errors: 4.0.3 @@ -8761,18 +7882,18 @@ snapshots: - supports-color - utf-8-validate - '@metamask/superstruct@3.2.1': {} + '@metamask/superstruct@3.3.0': {} - '@metamask/utils@11.10.0': + '@metamask/utils@11.11.0': dependencies: '@ethereumjs/tx': 4.2.0 - '@metamask/superstruct': 3.2.1 + '@metamask/superstruct': 3.3.0 '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.13 '@types/lodash': 4.17.24 debug: 4.4.3 - lodash: 4.17.23 + lodash: 4.18.1 pony-cause: 2.1.11 semver: 7.7.4 uuid: 9.0.1 @@ -8792,7 +7913,7 @@ snapshots: '@metamask/utils@8.5.0': dependencies: '@ethereumjs/tx': 4.2.0 - '@metamask/superstruct': 3.2.1 + '@metamask/superstruct': 3.3.0 '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.13 @@ -8806,7 +7927,7 @@ snapshots: '@metamask/utils@9.3.0': dependencies: '@ethereumjs/tx': 4.2.0 - '@metamask/superstruct': 3.2.1 + '@metamask/superstruct': 3.3.0 '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.13 @@ -8848,78 +7969,78 @@ snapshots: '@package-json/types@0.0.12': {} - '@parcel/watcher-android-arm64@2.5.6': + '@parcel/watcher-android-arm64@2.5.1': optional: true - '@parcel/watcher-darwin-arm64@2.5.6': + '@parcel/watcher-darwin-arm64@2.5.1': optional: true - '@parcel/watcher-darwin-x64@2.5.6': + '@parcel/watcher-darwin-x64@2.5.1': optional: true - '@parcel/watcher-freebsd-x64@2.5.6': + '@parcel/watcher-freebsd-x64@2.5.1': optional: true - '@parcel/watcher-linux-arm-glibc@2.5.6': + '@parcel/watcher-linux-arm-glibc@2.5.1': optional: true - '@parcel/watcher-linux-arm-musl@2.5.6': + '@parcel/watcher-linux-arm-musl@2.5.1': optional: true - '@parcel/watcher-linux-arm64-glibc@2.5.6': + '@parcel/watcher-linux-arm64-glibc@2.5.1': optional: true - '@parcel/watcher-linux-arm64-musl@2.5.6': + '@parcel/watcher-linux-arm64-musl@2.5.1': optional: true - '@parcel/watcher-linux-x64-glibc@2.5.6': + '@parcel/watcher-linux-x64-glibc@2.5.1': optional: true - '@parcel/watcher-linux-x64-musl@2.5.6': + '@parcel/watcher-linux-x64-musl@2.5.1': optional: true - '@parcel/watcher-win32-arm64@2.5.6': + '@parcel/watcher-win32-arm64@2.5.1': optional: true - '@parcel/watcher-win32-ia32@2.5.6': + '@parcel/watcher-win32-ia32@2.5.1': optional: true - '@parcel/watcher-win32-x64@2.5.6': + '@parcel/watcher-win32-x64@2.5.1': optional: true - '@parcel/watcher@2.5.6': + '@parcel/watcher@2.5.1': dependencies: - detect-libc: 2.1.2 + detect-libc: 1.0.3 is-glob: 4.0.3 + micromatch: 4.0.8 node-addon-api: 7.1.1 - picomatch: 4.0.3 optionalDependencies: - '@parcel/watcher-android-arm64': 2.5.6 - '@parcel/watcher-darwin-arm64': 2.5.6 - '@parcel/watcher-darwin-x64': 2.5.6 - '@parcel/watcher-freebsd-x64': 2.5.6 - '@parcel/watcher-linux-arm-glibc': 2.5.6 - '@parcel/watcher-linux-arm-musl': 2.5.6 - '@parcel/watcher-linux-arm64-glibc': 2.5.6 - '@parcel/watcher-linux-arm64-musl': 2.5.6 - '@parcel/watcher-linux-x64-glibc': 2.5.6 - '@parcel/watcher-linux-x64-musl': 2.5.6 - '@parcel/watcher-win32-arm64': 2.5.6 - '@parcel/watcher-win32-ia32': 2.5.6 - '@parcel/watcher-win32-x64': 2.5.6 + '@parcel/watcher-android-arm64': 2.5.1 + '@parcel/watcher-darwin-arm64': 2.5.1 + '@parcel/watcher-darwin-x64': 2.5.1 + '@parcel/watcher-freebsd-x64': 2.5.1 + '@parcel/watcher-linux-arm-glibc': 2.5.1 + '@parcel/watcher-linux-arm-musl': 2.5.1 + '@parcel/watcher-linux-arm64-glibc': 2.5.1 + '@parcel/watcher-linux-arm64-musl': 2.5.1 + '@parcel/watcher-linux-x64-glibc': 2.5.1 + '@parcel/watcher-linux-x64-musl': 2.5.1 + '@parcel/watcher-win32-arm64': 2.5.1 + '@parcel/watcher-win32-ia32': 2.5.1 + '@parcel/watcher-win32-x64': 2.5.1 '@paulmillr/qr@0.2.1': {} - '@polygonlabs/apps-team-lint@2.0.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': + '@polygonlabs/apps-team-lint@2.0.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3))(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@commitlint/config-conventional': 19.8.1 - eslint: 10.0.3(jiti@2.6.1) - eslint-config-prettier: 10.1.8(eslint@10.0.3(jiti@2.6.1)) - eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1)))(eslint@10.0.3(jiti@2.6.1)) - eslint-plugin-import-x: 4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1)) - eslint-plugin-perfectionist: 5.6.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + eslint: 10.0.3(jiti@2.7.0) + eslint-config-prettier: 10.1.8(eslint@10.0.3(jiti@2.7.0)) + eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3))(eslint@10.0.3(jiti@2.7.0)))(eslint@10.0.3(jiti@2.7.0)) + eslint-plugin-import-x: 4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3))(eslint@10.0.3(jiti@2.7.0)) + eslint-plugin-perfectionist: 5.6.0(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) globals: 17.4.0 - typescript-eslint: 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + typescript-eslint: 8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -8928,6 +8049,15 @@ snapshots: - eslint-plugin-import - supports-color + '@polygonlabs/oms-wallet@0.2.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6)': + dependencies: + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + - zod + '@polymarket/clob-client-v2@1.0.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6)': dependencies: '@ethersproject/providers': 5.8.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) @@ -8935,7 +8065,7 @@ snapshots: axios: 1.13.6 browser-or-node: 3.0.0 tslib: 2.8.1 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6) transitivePeerDependencies: - bufferutil - debug @@ -8954,21 +8084,20 @@ snapshots: '@ethersproject/providers': 5.8.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@ethersproject/solidity': 5.8.0 - '@poppinss/colors@4.1.6': - dependencies: - kleur: 4.1.5 - - '@poppinss/dumper@0.6.5': - dependencies: - '@poppinss/colors': 4.1.6 - '@sindresorhus/is': 7.2.0 - supports-color: 10.2.2 + '@radix-ui/number@1.1.2': {} - '@poppinss/exception@1.2.3': {} + '@radix-ui/primitive@1.1.3': {} - '@radix-ui/number@1.1.1': {} + '@radix-ui/primitive@1.1.4': {} - '@radix-ui/primitive@1.1.3': {} + '@radix-ui/react-arrow@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.28 + '@types/react-dom': 18.3.7(@types/react@18.3.28) '@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: @@ -8979,53 +8108,53 @@ snapshots: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-aspect-ratio@1.1.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-aspect-ratio@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-checkbox@1.3.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-checkbox@1.3.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-presence': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.2(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-collapsible@1.1.12(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-collapsible@1.1.15(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-id': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-presence': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-collection@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-collection@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.3.0(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: @@ -9038,32 +8167,38 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 - '@radix-ui/react-context@1.1.2(@types/react@18.3.28)(react@18.3.1)': + '@radix-ui/react-compose-refs@1.1.3(@types/react@18.3.28)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: '@types/react': 18.3.28 - '@radix-ui/react-context@1.1.3(@types/react@18.3.28)(react@18.3.1)': + '@radix-ui/react-context@1.1.2(@types/react@18.3.28)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: '@types/react': 18.3.28 - '@radix-ui/react-dialog@1.1.15(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-context@1.1.4(@types/react@18.3.28)(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 + + '@radix-ui/react-dialog@1.1.18(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-portal': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.3.0(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -9072,7 +8207,7 @@ snapshots: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-direction@1.1.1(@types/react@18.3.28)(react@18.3.1)': + '@radix-ui/react-direction@1.1.2(@types/react@18.3.28)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: @@ -9091,32 +8226,45 @@ snapshots: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dismissable-layer@1.1.14(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-effect-event': 0.0.3(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-focus-guards@1.1.3(@types/react@18.3.28)(react@18.3.1)': + '@radix-ui/react-dropdown-menu@2.1.19(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-id': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-menu': 2.1.19(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 + '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-focus-guards@1.1.4(@types/react@18.3.28)(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 + + '@radix-ui/react-focus-scope@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: @@ -9130,24 +8278,31 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 - '@radix-ui/react-menu@2.1.16(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-id@1.1.2(@types/react@18.3.28)(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 + + '@radix-ui/react-menu@2.1.19(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-collection': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-direction': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-popper': 1.3.2(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.3.0(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@18.3.28)(react@18.3.1) aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -9174,6 +8329,34 @@ snapshots: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) + '@radix-ui/react-popper@1.3.2(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/rect': 1.1.2 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.28 + '@types/react-dom': 18.3.7(@types/react@18.3.28) + + '@radix-ui/react-portal@1.1.13(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.28 + '@types/react-dom': 18.3.7(@types/react@18.3.28) + '@radix-ui/react-portal@1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -9194,6 +8377,15 @@ snapshots: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) + '@radix-ui/react-presence@1.1.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.28 + '@types/react-dom': 18.3.7(@types/react@18.3.28) + '@radix-ui/react-primitive@2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) @@ -9203,81 +8395,82 @@ snapshots: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-primitive@2.1.4(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-primitive@2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-slot': 1.2.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-slot': 1.3.0(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-progress@1.1.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-progress@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-context': 1.1.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-radio-group@1.3.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-radio-group@1.4.2(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-direction': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-presence': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.2(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-roving-focus@1.1.14(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-collection': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-direction': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-id': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-select@2.2.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-select@2.3.2(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/number': 1.1.2 + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-collection': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-direction': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-popper': 1.3.2(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.3.0(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -9293,58 +8486,58 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 - '@radix-ui/react-slot@1.2.4(@types/react@18.3.28)(react@18.3.1)': + '@radix-ui/react-slot@1.3.0(@types/react@18.3.28)(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 optionalDependencies: '@types/react': 18.3.28 - '@radix-ui/react-switch@1.2.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-switch@1.3.2(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.2(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-tabs@1.1.13(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-tabs@1.1.16(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-direction': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-id': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-presence': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-toast@1.2.15(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toast@1.2.18(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-collection': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.4(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: @@ -9377,6 +8570,12 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 + '@radix-ui/react-use-callback-ref@1.1.2(@types/react@18.3.28)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.28)(react@18.3.1)': dependencies: '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.28)(react@18.3.1) @@ -9385,6 +8584,14 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 + '@radix-ui/react-use-controllable-state@1.2.3(@types/react@18.3.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 + '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.28)(react@18.3.1)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) @@ -9392,6 +8599,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 + '@radix-ui/react-use-effect-event@0.0.3(@types/react@18.3.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.28)(react@18.3.1)': dependencies: '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) @@ -9405,7 +8619,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 - '@radix-ui/react-use-previous@1.1.1(@types/react@18.3.28)(react@18.3.1)': + '@radix-ui/react-use-layout-effect@1.1.2(@types/react@18.3.28)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 + + '@radix-ui/react-use-previous@1.1.2(@types/react@18.3.28)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: @@ -9418,6 +8638,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 + '@radix-ui/react-use-rect@1.1.2(@types/react@18.3.28)(react@18.3.1)': + dependencies: + '@radix-ui/rect': 1.1.2 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 + '@radix-ui/react-use-size@1.1.1(@types/react@18.3.28)(react@18.3.1)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) @@ -9425,6 +8652,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 + '@radix-ui/react-use-size@1.1.2(@types/react@18.3.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 + '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -9434,9 +8668,9 @@ snapshots: '@types/react': 18.3.28 '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@radix-ui/react-visually-hidden@1.2.4(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-visually-hidden@1.2.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: @@ -9445,6 +8679,8 @@ snapshots: '@radix-ui/rect@1.1.1': {} + '@radix-ui/rect@1.1.2': {} + '@react-oauth/google@0.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: react: 18.3.1 @@ -9454,7 +8690,7 @@ snapshots: dependencies: big.js: 6.2.2 dayjs: 1.11.13 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.22.4) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.22.4) transitivePeerDependencies: - bufferutil - typescript @@ -9465,20 +8701,20 @@ snapshots: dependencies: big.js: 6.2.2 dayjs: 1.11.13 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) transitivePeerDependencies: - bufferutil - typescript - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + '@reown/appkit-controllers@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) valtio: 1.13.2(@types/react@18.3.28)(react@18.3.1) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -9507,12 +8743,12 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-pay@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + '@reown/appkit-pay@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) lit: 3.3.0 valtio: 1.13.2(@types/react@18.3.28)(react@18.3.1) transitivePeerDependencies: @@ -9547,12 +8783,12 @@ snapshots: dependencies: buffer: 6.0.3 - '@reown/appkit-scaffold-ui@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76)': + '@reown/appkit-scaffold-ui@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) lit: 3.3.0 transitivePeerDependencies: @@ -9584,10 +8820,10 @@ snapshots: - valtio - zod - '@reown/appkit-ui@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + '@reown/appkit-ui@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) lit: 3.3.0 qrcode: 1.5.3 @@ -9619,16 +8855,16 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76)': + '@reown/appkit-utils@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) valtio: 1.13.2(@types/react@18.3.28)(react@18.3.1) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -9668,21 +8904,21 @@ snapshots: - typescript - utf-8-validate - '@reown/appkit@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + '@reown/appkit@1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-pay': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@reown/appkit-pay': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-scaffold-ui': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) + '@reown/appkit-scaffold-ui': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(valtio@1.13.2(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) '@walletconnect/types': 2.21.0 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) bs58: 6.0.0 valtio: 1.13.2(@types/react@18.3.28)(react@18.3.1) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -9713,79 +8949,79 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.27': {} - '@rollup/rollup-android-arm-eabi@4.59.0': + '@rollup/rollup-android-arm-eabi@4.62.2': optional: true - '@rollup/rollup-android-arm64@4.59.0': + '@rollup/rollup-android-arm64@4.62.2': optional: true - '@rollup/rollup-darwin-arm64@4.59.0': + '@rollup/rollup-darwin-arm64@4.62.2': optional: true - '@rollup/rollup-darwin-x64@4.59.0': + '@rollup/rollup-darwin-x64@4.62.2': optional: true - '@rollup/rollup-freebsd-arm64@4.59.0': + '@rollup/rollup-freebsd-arm64@4.62.2': optional: true - '@rollup/rollup-freebsd-x64@4.59.0': + '@rollup/rollup-freebsd-x64@4.62.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.59.0': + '@rollup/rollup-linux-arm-musleabihf@4.62.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.59.0': + '@rollup/rollup-linux-arm64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.59.0': + '@rollup/rollup-linux-arm64-musl@4.62.2': optional: true - '@rollup/rollup-linux-loong64-gnu@4.59.0': + '@rollup/rollup-linux-loong64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-loong64-musl@4.59.0': + '@rollup/rollup-linux-loong64-musl@4.62.2': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.59.0': + '@rollup/rollup-linux-ppc64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-ppc64-musl@4.59.0': + '@rollup/rollup-linux-ppc64-musl@4.62.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.59.0': + '@rollup/rollup-linux-riscv64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-riscv64-musl@4.59.0': + '@rollup/rollup-linux-riscv64-musl@4.62.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.59.0': + '@rollup/rollup-linux-s390x-gnu@4.62.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.59.0': + '@rollup/rollup-linux-x64-gnu@4.62.2': optional: true - '@rollup/rollup-linux-x64-musl@4.59.0': + '@rollup/rollup-linux-x64-musl@4.62.2': optional: true - '@rollup/rollup-openbsd-x64@4.59.0': + '@rollup/rollup-openbsd-x64@4.62.2': optional: true - '@rollup/rollup-openharmony-arm64@4.59.0': + '@rollup/rollup-openharmony-arm64@4.62.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.59.0': + '@rollup/rollup-win32-arm64-msvc@4.62.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.59.0': + '@rollup/rollup-win32-ia32-msvc@4.62.2': optional: true - '@rollup/rollup-win32-x64-gnu@4.59.0': + '@rollup/rollup-win32-x64-gnu@4.62.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.59.0': + '@rollup/rollup-win32-x64-msvc@4.62.2': optional: true '@safe-global/safe-apps-provider@0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': @@ -9801,7 +9037,7 @@ snapshots: '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': dependencies: '@safe-global/safe-gateway-typescript-sdk': 3.23.1 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) transitivePeerDependencies: - bufferutil - typescript @@ -9849,8 +9085,6 @@ snapshots: '@simple-libs/stream-utils@1.2.0': {} - '@sindresorhus/is@7.2.0': {} - '@socket.io/component-emitter@3.1.2': {} '@solana-program/system@0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6))': @@ -10133,7 +9367,7 @@ snapshots: '@solana/functional': 5.5.1(typescript@5.9.3) '@solana/rpc-subscriptions-spec': 5.5.1(typescript@5.9.3) '@solana/subscribable': 5.5.1(typescript@5.9.3) - ws: 8.20.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -10186,7 +9420,7 @@ snapshots: '@solana/errors': 5.5.1(typescript@5.9.3) '@solana/rpc-spec': 5.5.1(typescript@5.9.3) '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) - undici-types: 7.24.6 + undici-types: 7.28.0 optionalDependencies: typescript: 5.9.3 @@ -10306,43 +9540,43 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/wallet-adapter-base@0.9.27(@solana/web3.js@1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6))': + '@solana/wallet-adapter-base@0.9.27(@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6))': dependencies: - '@solana/wallet-standard-features': 1.3.0 - '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@wallet-standard/base': 1.1.0 - '@wallet-standard/features': 1.1.0 + '@solana/wallet-standard-features': 1.4.0 + '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + '@wallet-standard/base': 1.1.1 + '@wallet-standard/features': 1.1.1 eventemitter3: 5.0.1 - '@solana/wallet-standard-chains@1.1.1': + '@solana/wallet-standard-chains@1.1.2': dependencies: - '@wallet-standard/base': 1.1.0 + '@wallet-standard/base': 1.1.1 - '@solana/wallet-standard-features@1.3.0': + '@solana/wallet-standard-features@1.4.0': dependencies: - '@wallet-standard/base': 1.1.0 - '@wallet-standard/features': 1.1.0 + '@wallet-standard/base': 1.1.1 + '@wallet-standard/features': 1.1.1 - '@solana/wallet-standard-util@1.1.2': + '@solana/wallet-standard-util@1.1.3': dependencies: '@noble/curves': 1.9.7 - '@solana/wallet-standard-chains': 1.1.1 - '@solana/wallet-standard-features': 1.3.0 - - '@solana/wallet-standard-wallet-adapter-base@1.1.4(@solana/web3.js@1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6))(bs58@6.0.0)': - dependencies: - '@solana/wallet-adapter-base': 0.9.27(@solana/web3.js@1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)) - '@solana/wallet-standard-chains': 1.1.1 - '@solana/wallet-standard-features': 1.3.0 - '@solana/wallet-standard-util': 1.1.2 - '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6) - '@wallet-standard/app': 1.1.0 - '@wallet-standard/base': 1.1.0 - '@wallet-standard/features': 1.1.0 - '@wallet-standard/wallet': 1.1.0 + '@solana/wallet-standard-chains': 1.1.2 + '@solana/wallet-standard-features': 1.4.0 + + '@solana/wallet-standard-wallet-adapter-base@1.1.5(@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6))(bs58@6.0.0)': + dependencies: + '@solana/wallet-adapter-base': 0.9.27(@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)) + '@solana/wallet-standard-chains': 1.1.2 + '@solana/wallet-standard-features': 1.4.0 + '@solana/wallet-standard-util': 1.1.3 + '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6) + '@wallet-standard/app': 1.1.1 + '@wallet-standard/base': 1.1.1 + '@wallet-standard/features': 1.1.1 + '@wallet-standard/wallet': 1.1.1 bs58: 6.0.0 - '@solana/web3.js@1.98.4(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: '@babel/runtime': 7.29.2 '@noble/curves': 1.9.7 @@ -10356,8 +9590,8 @@ snapshots: buffer: 6.0.3 fast-stable-stringify: 1.0.0 jayson: 4.3.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - node-fetch: 2.7.0(encoding@0.1.13) - rpc-websockets: 9.3.7 + node-fetch: 2.7.0 + rpc-websockets: 9.3.9 superstruct: 2.0.2 transitivePeerDependencies: - bufferutil @@ -10365,8 +9599,6 @@ snapshots: - typescript - utf-8-validate - '@speed-highlight/core@1.2.14': {} - '@spruceid/siwe-parser@2.1.2': dependencies: '@noble/hashes': 1.8.0 @@ -10387,167 +9619,106 @@ snapshots: '@stablelib/wipe@1.0.1': {} - '@swc/helpers@0.5.20': + '@swc/helpers@0.5.23': dependencies: tslib: 2.8.1 - '@tailwindcss/cli@4.2.2': + '@tailwindcss/cli@4.3.2': dependencies: - '@parcel/watcher': 2.5.6 - '@tailwindcss/node': 4.2.2 - '@tailwindcss/oxide': 4.2.2 - enhanced-resolve: 5.20.0 + '@parcel/watcher': 2.5.1 + '@tailwindcss/node': 4.3.2 + '@tailwindcss/oxide': 4.3.2 + enhanced-resolve: 5.21.6 mri: 1.2.0 picocolors: 1.1.1 - tailwindcss: 4.2.2 - - '@tailwindcss/node@4.2.1': - dependencies: - '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.20.0 - jiti: 2.6.1 - lightningcss: 1.31.1 - magic-string: 0.30.21 - source-map-js: 1.2.1 - tailwindcss: 4.2.1 + tailwindcss: 4.3.2 - '@tailwindcss/node@4.2.2': + '@tailwindcss/node@4.3.2': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.20.0 - jiti: 2.6.1 + enhanced-resolve: 5.21.6 + jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.2.2 - - '@tailwindcss/oxide-android-arm64@4.2.1': - optional: true - - '@tailwindcss/oxide-android-arm64@4.2.2': - optional: true - - '@tailwindcss/oxide-darwin-arm64@4.2.1': - optional: true - - '@tailwindcss/oxide-darwin-arm64@4.2.2': - optional: true - - '@tailwindcss/oxide-darwin-x64@4.2.1': - optional: true - - '@tailwindcss/oxide-darwin-x64@4.2.2': - optional: true + tailwindcss: 4.3.2 - '@tailwindcss/oxide-freebsd-x64@4.2.1': + '@tailwindcss/oxide-android-arm64@4.3.2': optional: true - '@tailwindcss/oxide-freebsd-x64@4.2.2': + '@tailwindcss/oxide-darwin-arm64@4.3.2': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': + '@tailwindcss/oxide-darwin-x64@4.3.2': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': + '@tailwindcss/oxide-freebsd-x64@4.3.2': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.2.1': + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.2.2': + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.2.1': + '@tailwindcss/oxide-linux-x64-musl@4.3.2': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.2.2': + '@tailwindcss/oxide-wasm32-wasi@4.3.2': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.2.1': + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.2.2': + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.2.1': - optional: true - - '@tailwindcss/oxide-wasm32-wasi@4.2.2': - optional: true - - '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': - optional: true - - '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': - optional: true - - '@tailwindcss/oxide-win32-x64-msvc@4.2.1': - optional: true - - '@tailwindcss/oxide-win32-x64-msvc@4.2.2': - optional: true - - '@tailwindcss/oxide@4.2.1': + '@tailwindcss/oxide@4.3.2': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.2.1 - '@tailwindcss/oxide-darwin-arm64': 4.2.1 - '@tailwindcss/oxide-darwin-x64': 4.2.1 - '@tailwindcss/oxide-freebsd-x64': 4.2.1 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.1 - '@tailwindcss/oxide-linux-arm64-gnu': 4.2.1 - '@tailwindcss/oxide-linux-arm64-musl': 4.2.1 - '@tailwindcss/oxide-linux-x64-gnu': 4.2.1 - '@tailwindcss/oxide-linux-x64-musl': 4.2.1 - '@tailwindcss/oxide-wasm32-wasi': 4.2.1 - '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1 - '@tailwindcss/oxide-win32-x64-msvc': 4.2.1 + '@tailwindcss/oxide-android-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-x64': 4.3.2 + '@tailwindcss/oxide-freebsd-x64': 4.3.2 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.2 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-x64-musl': 4.3.2 + '@tailwindcss/oxide-wasm32-wasi': 4.3.2 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.2 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.2 - '@tailwindcss/oxide@4.2.2': - optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.2.2 - '@tailwindcss/oxide-darwin-arm64': 4.2.2 - '@tailwindcss/oxide-darwin-x64': 4.2.2 - '@tailwindcss/oxide-freebsd-x64': 4.2.2 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.2 - '@tailwindcss/oxide-linux-arm64-gnu': 4.2.2 - '@tailwindcss/oxide-linux-arm64-musl': 4.2.2 - '@tailwindcss/oxide-linux-x64-gnu': 4.2.2 - '@tailwindcss/oxide-linux-x64-musl': 4.2.2 - '@tailwindcss/oxide-wasm32-wasi': 4.2.2 - '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 - '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 - - '@tailwindcss/vite@4.2.1(vite@5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1))': + '@tailwindcss/vite@4.3.2(vite@5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1))': dependencies: - '@tailwindcss/node': 4.2.1 - '@tailwindcss/oxide': 4.2.1 - tailwindcss: 4.2.1 - vite: 5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1) + '@tailwindcss/node': 4.3.2 + '@tailwindcss/oxide': 4.3.2 + tailwindcss: 4.3.2 + vite: 5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) - '@tanstack/query-core@5.95.2': {} + '@tanstack/query-core@5.101.2': {} - '@tanstack/query-persist-client-core@5.95.2': + '@tanstack/query-persist-client-core@5.101.2': dependencies: - '@tanstack/query-core': 5.95.2 + '@tanstack/query-core': 5.101.2 - '@tanstack/react-query@5.95.2(react@18.3.1)': + '@tanstack/react-query@5.101.2(react@18.3.1)': dependencies: - '@tanstack/query-core': 5.95.2 + '@tanstack/query-core': 5.101.2 react: 18.3.1 - '@tanstack/react-virtual@3.13.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@tanstack/react-virtual@3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/virtual-core': 3.13.23 + '@tanstack/virtual-core': 3.17.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@tanstack/virtual-core@3.13.23': {} + '@tanstack/virtual-core@3.17.3': {} '@tsconfig/node-ts@23.6.4': {} @@ -10560,7 +9731,7 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.29.0 + '@babel/parser': 7.24.1 '@babel/types': 7.29.0 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 @@ -10572,13 +9743,18 @@ snapshots: '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.29.0 + '@babel/parser': 7.24.1 '@babel/types': 7.29.0 '@types/babel__traverse@7.28.0': dependencies: '@babel/types': 7.29.0 + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + '@types/connect@3.4.38': dependencies: '@types/node': 22.19.13 @@ -10591,10 +9767,14 @@ snapshots: dependencies: '@types/ms': 2.1.0 + '@types/deep-eql@4.0.2': {} + '@types/esrecurse@4.3.1': {} '@types/estree@1.0.8': {} + '@types/estree@1.0.9': {} + '@types/json-schema@7.0.15': {} '@types/lodash@4.17.24': {} @@ -10611,11 +9791,6 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/node@25.3.3': - dependencies: - undici-types: 7.18.2 - optional: true - '@types/prop-types@15.7.15': {} '@types/react-dom@18.3.7(@types/react@18.3.28)': @@ -10645,15 +9820,15 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3))(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.56.1 - '@typescript-eslint/type-utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.56.1 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.0.3(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.4.0(typescript@5.9.3) @@ -10661,14 +9836,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.56.1 '@typescript-eslint/types': 8.56.1 '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.56.1 debug: 4.4.3 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.0.3(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -10691,13 +9866,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.56.1 '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) debug: 4.4.3 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.0.3(jiti@2.7.0) ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -10720,13 +9895,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.7.0)) '@typescript-eslint/scope-manager': 8.56.1 '@typescript-eslint/types': 8.56.1 '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.0.3(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -10795,75 +9970,73 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1))': + '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1))': dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.7 + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1) + vite: 5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) transitivePeerDependencies: - supports-color - '@vitest/expect@3.1.4': + '@vitest/expect@3.2.7': dependencies: - '@vitest/spy': 3.1.4 - '@vitest/utils': 3.1.4 + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.7 + '@vitest/utils': 3.2.7 chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.4(vite@5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1))': + '@vitest/mocker@3.2.7(vite@5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1))': dependencies: - '@vitest/spy': 3.1.4 + '@vitest/spy': 3.2.7 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1) - - '@vitest/pretty-format@3.1.4': - dependencies: - tinyrainbow: 2.0.0 + vite: 5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) - '@vitest/pretty-format@3.2.4': + '@vitest/pretty-format@3.2.7': dependencies: tinyrainbow: 2.0.0 - '@vitest/runner@3.1.4': + '@vitest/runner@3.2.7': dependencies: - '@vitest/utils': 3.1.4 + '@vitest/utils': 3.2.7 pathe: 2.0.3 + strip-literal: 3.1.0 - '@vitest/snapshot@3.1.4': + '@vitest/snapshot@3.2.7': dependencies: - '@vitest/pretty-format': 3.1.4 + '@vitest/pretty-format': 3.2.7 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@3.1.4': + '@vitest/spy@3.2.7': dependencies: - tinyspy: 3.0.2 + tinyspy: 4.0.4 - '@vitest/utils@3.1.4': + '@vitest/utils@3.2.7': dependencies: - '@vitest/pretty-format': 3.1.4 + '@vitest/pretty-format': 3.2.7 loupe: 3.2.1 tinyrainbow: 2.0.0 - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(@wagmi/core@2.22.1(@tanstack/query-core@5.95.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)': + '@wagmi/connectors@6.2.0(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)': dependencies: - '@base-org/account': 2.4.0(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(utf-8-validate@6.0.6)(zod@3.25.76) + '@base-org/account': 2.4.0(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(utf-8-validate@6.0.6)(zod@3.25.76) '@coinbase/wallet-sdk': 4.3.6(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(utf-8-validate@6.0.6)(zod@3.25.76) - '@gemini-wallet/core': 0.3.2(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) - '@metamask/sdk': 0.33.1(bufferutil@4.1.0)(encoding@0.1.13)(utf-8-validate@6.0.6) + '@gemini-wallet/core': 0.3.2(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + '@metamask/sdk': 0.33.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.95.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.101.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(@wagmi/core@2.22.1(@tanstack/query-core@5.95.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + porto: 0.2.35(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -10904,14 +10077,14 @@ snapshots: - wagmi - zod - '@wagmi/core@2.22.1(@tanstack/query-core@5.95.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))': + '@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))': dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@5.9.3) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zustand: 5.0.0(@types/react@18.3.28)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)) optionalDependencies: - '@tanstack/query-core': 5.95.2 + '@tanstack/query-core': 5.101.2 typescript: 5.9.3 transitivePeerDependencies: - '@types/react' @@ -10919,19 +10092,19 @@ snapshots: - react - use-sync-external-store - '@wallet-standard/app@1.1.0': + '@wallet-standard/app@1.1.1': dependencies: - '@wallet-standard/base': 1.1.0 + '@wallet-standard/base': 1.1.1 - '@wallet-standard/base@1.1.0': {} + '@wallet-standard/base@1.1.1': {} - '@wallet-standard/features@1.1.0': + '@wallet-standard/features@1.1.1': dependencies: - '@wallet-standard/base': 1.1.0 + '@wallet-standard/base': 1.1.1 - '@wallet-standard/wallet@1.1.0': + '@wallet-standard/wallet@1.1.1': dependencies: - '@wallet-standard/base': 1.1.0 + '@wallet-standard/base': 1.1.1 '@walletconnect/core@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': dependencies: @@ -11025,17 +10198,17 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/ethereum-provider@2.21.1(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + '@walletconnect/ethereum-provider@2.21.1(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': dependencies: - '@reown/appkit': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) - '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) + '@reown/appkit': 1.7.8(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@walletconnect/jsonrpc-http-connection': 1.0.8 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1 '@walletconnect/sign-client': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) '@walletconnect/types': 2.21.1 - '@walletconnect/universal-provider': 2.21.1(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) '@walletconnect/utils': 2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) events: 3.3.0 transitivePeerDependencies: @@ -11077,11 +10250,11 @@ snapshots: '@walletconnect/time': 1.0.2 events: 3.3.0 - '@walletconnect/jsonrpc-http-connection@1.0.8(encoding@0.1.13)': + '@walletconnect/jsonrpc-http-connection@1.0.8': dependencies: '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/safe-json': 1.0.2 - cross-fetch: 3.2.0(encoding@0.1.13) + cross-fetch: 3.2.0 events: 3.3.0 transitivePeerDependencies: - encoding @@ -11108,7 +10281,7 @@ snapshots: '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/safe-json': 1.0.2 events: 3.3.0 - ws: 7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 7.5.11(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -11116,8 +10289,8 @@ snapshots: '@walletconnect/keyvaluestorage@1.1.1': dependencies: '@walletconnect/safe-json': 1.0.2 - idb-keyval: 6.2.2 - unstorage: 1.17.5(idb-keyval@6.2.2) + idb-keyval: 6.2.6 + unstorage: 1.17.5(idb-keyval@6.2.6) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -11293,10 +10466,10 @@ snapshots: - ioredis - uploadthing - '@walletconnect/universal-provider@2.21.0(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + '@walletconnect/universal-provider@2.21.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': dependencies: '@walletconnect/events': 1.0.1 - '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) + '@walletconnect/jsonrpc-http-connection': 1.0.8 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 @@ -11333,10 +10506,10 @@ snapshots: - utf-8-validate - zod - '@walletconnect/universal-provider@2.21.1(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': + '@walletconnect/universal-provider@2.21.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)': dependencies: '@walletconnect/events': 1.0.1 - '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) + '@walletconnect/jsonrpc-http-connection': 1.0.8 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 @@ -11478,7 +10651,7 @@ snapshots: dependencies: '@x402/core': 2.5.0 '@x402/extensions': 2.5.0(bufferutil@4.1.0)(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(typescript@5.9.3)(utf-8-validate@6.0.6) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zod: 3.25.76 transitivePeerDependencies: - bufferutil @@ -11493,7 +10666,7 @@ snapshots: ajv: 8.18.0 siwe: 2.3.2(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) tweetnacl: 1.0.3 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zod: 3.25.76 transitivePeerDependencies: - bufferutil @@ -11504,15 +10677,13 @@ snapshots: '@x402/fetch@2.5.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: '@x402/core': 2.5.0 - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zod: 3.25.76 transitivePeerDependencies: - bufferutil - typescript - utf-8-validate - '@zeit/schemas@2.36.0': {} - abitype@1.0.6(typescript@5.9.3)(zod@3.25.76): optionalDependencies: typescript: 5.9.3 @@ -11548,6 +10719,12 @@ snapshots: aes-js@4.0.0-beta.5: {} + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + agentkeepalive@4.6.0: dependencies: humanize-ms: 1.2.1 @@ -11559,13 +10736,6 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.12.0: - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 @@ -11573,10 +10743,6 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - ansi-align@3.0.1: - dependencies: - string-width: 4.2.3 - ansi-colors@4.1.3: {} ansi-escapes@7.3.0: @@ -11600,10 +10766,6 @@ snapshots: apg-js@4.4.0: {} - arch@2.2.0: {} - - arg@5.0.2: {} - argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -11618,12 +10780,6 @@ snapshots: array-union@2.1.0: {} - asn1js@3.0.7: - dependencies: - pvtsutils: 1.3.6 - pvutils: 1.1.5 - tslib: 2.8.1 - assertion-error@2.0.1: {} async-mutex@0.2.6: @@ -11640,9 +10796,9 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - axios-retry@4.5.0(axios@1.13.6): + axios-retry@4.5.0(axios@1.16.0): dependencies: - axios: 1.13.6 + axios: 1.16.0 is-retry-allowed: 2.2.0 axios@1.13.6: @@ -11653,7 +10809,23 @@ snapshots: transitivePeerDependencies: - debug - balanced-match@1.0.2: {} + axios@1.16.0: + dependencies: + follow-redirects: 1.16.0 + form-data: 4.0.5 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + + axios@1.18.0: + dependencies: + follow-redirects: 1.16.0 + form-data: 4.0.5 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color balanced-match@4.0.4: {} @@ -11675,10 +10847,6 @@ snapshots: big.js@6.2.2: {} - blake3-wasm@2.1.5: {} - - blakejs@1.2.1: {} - bn.js@4.12.3: {} bn.js@5.2.3: {} @@ -11691,22 +10859,6 @@ snapshots: bowser@2.14.1: {} - boxen@7.0.0: - dependencies: - ansi-align: 3.0.1 - camelcase: 7.0.1 - chalk: 5.0.1 - cli-boxes: 3.0.0 - string-width: 5.1.2 - type-fest: 2.19.0 - widest-line: 4.0.1 - wrap-ansi: 8.1.0 - - brace-expansion@1.1.12: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - brace-expansion@5.0.4: dependencies: balanced-match: 4.0.4 @@ -11751,12 +10903,6 @@ snapshots: dependencies: run-applescript: 7.1.0 - bytes@3.0.0: {} - - bytes@3.1.2: {} - - bytestreamjs@2.0.1: {} - cac@6.7.14: {} call-bind-apply-helpers@1.0.2: @@ -11764,7 +10910,7 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 - call-bind@1.0.8: + call-bind@1.0.9: dependencies: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 @@ -11780,12 +10926,8 @@ snapshots: camelcase@5.3.1: {} - camelcase@7.0.1: {} - caniuse-lite@1.0.30001775: {} - cbor2@1.12.0: {} - chai@5.3.3: dependencies: assertion-error: 2.0.1 @@ -11794,17 +10936,11 @@ snapshots: loupe: 3.2.1 pathval: 2.0.1 - chalk-template@0.4.0: - dependencies: - chalk: 4.1.2 - chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.0.1: {} - chalk@5.6.2: {} chardet@2.1.1: {} @@ -11843,12 +10979,6 @@ snapshots: slice-ansi: 8.0.0 string-width: 8.2.0 - clipboardy@3.0.0: - dependencies: - arch: 2.2.0 - execa: 5.1.1 - is-wsl: 2.2.0 - cliui@6.0.0: dependencies: string-width: 4.2.3 @@ -11861,12 +10991,6 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - cliui@9.0.1: - dependencies: - string-width: 7.2.0 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 - clsx@1.2.1: {} clsx@2.1.1: {} @@ -11902,24 +11026,6 @@ snapshots: array-ify: 1.0.0 dot-prop: 5.3.0 - compressible@2.0.18: - dependencies: - mime-db: 1.54.0 - - compression@1.8.1: - dependencies: - bytes: 3.1.2 - compressible: 2.0.18 - debug: 2.6.9 - negotiator: 0.6.4 - on-headers: 1.1.0 - safe-buffer: 5.2.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - - concat-map@0.0.1: {} - concurrently@9.2.1: dependencies: chalk: 4.1.2 @@ -11929,8 +11035,6 @@ snapshots: tree-kill: 1.2.2 yargs: 17.7.2 - content-disposition@0.5.2: {} - conventional-changelog-angular@8.2.0: dependencies: compare-func: 2.0.0 @@ -11952,9 +11056,7 @@ snapshots: convert-to-spaces@2.0.1: {} - cookie-es@1.2.2: {} - - cookie@1.1.1: {} + cookie-es@1.2.3: {} core-util-is@1.0.3: {} @@ -11976,15 +11078,15 @@ snapshots: crc-32@1.2.2: {} - cross-fetch@3.2.0(encoding@0.1.13): + cross-fetch@3.2.0: dependencies: - node-fetch: 2.7.0(encoding@0.1.13) + node-fetch: 2.7.0 transitivePeerDependencies: - encoding - cross-fetch@4.1.0(encoding@0.1.13): + cross-fetch@4.1.0: dependencies: - node-fetch: 2.7.0(encoding@0.1.13) + node-fetch: 2.7.0 transitivePeerDependencies: - encoding @@ -12010,10 +11112,6 @@ snapshots: dayjs@1.11.13: {} - debug@2.6.9: - dependencies: - ms: 2.0.0 - debug@4.3.4: dependencies: ms: 2.1.2 @@ -12028,8 +11126,6 @@ snapshots: deep-eql@5.0.2: {} - deep-extend@0.6.0: {} - deep-is@0.1.4: {} default-browser-id@5.0.1: {} @@ -12047,7 +11143,7 @@ snapshots: define-lazy-prop@3.0.0: {} - defu@6.1.4: {} + defu@6.1.7: {} delay@5.0.0: {} @@ -12063,6 +11159,8 @@ snapshots: detect-indent@6.1.0: {} + detect-libc@1.0.3: {} + detect-libc@2.1.2: {} detect-node-es@1.1.0: {} @@ -12079,8 +11177,6 @@ snapshots: dotenv@16.6.1: {} - dotenv@17.3.1: {} - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -12094,11 +11190,9 @@ snapshots: readable-stream: 3.6.2 stream-shift: 1.0.3 - eastasianwidth@0.2.0: {} - eciesjs@0.4.18: dependencies: - '@ecies/ciphers': 0.2.5(@noble/ciphers@1.3.0) + '@ecies/ciphers': 0.2.6(@noble/ciphers@1.3.0) '@noble/ciphers': 1.3.0 '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 @@ -12119,25 +11213,18 @@ snapshots: emoji-regex@8.0.0: {} - emoji-regex@9.2.2: {} - encode-utf8@1.0.3: {} - encoding@0.1.13: - dependencies: - iconv-lite: 0.6.3 - optional: true - end-of-stream@1.4.5: dependencies: once: 1.4.0 - engine.io-client@6.6.4(bufferutil@4.1.0)(utf-8-validate@6.0.6): + engine.io-client@6.6.6(bufferutil@4.1.0)(utf-8-validate@6.0.6): dependencies: '@socket.io/component-emitter': 3.1.2 debug: 4.4.3 engine.io-parser: 5.2.3 - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) xmlhttprequest-ssl: 2.1.2 transitivePeerDependencies: - bufferutil @@ -12146,10 +11233,10 @@ snapshots: engine.io-parser@5.2.3: {} - enhanced-resolve@5.20.0: + enhanced-resolve@5.21.6: dependencies: graceful-fs: 4.2.11 - tapable: 2.3.0 + tapable: 2.3.3 enquirer@2.4.1: dependencies: @@ -12164,8 +11251,6 @@ snapshots: dependencies: is-arrayish: 0.2.1 - error-stack-parser-es@1.0.5: {} - es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -12281,9 +11366,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.0.3(jiti@2.6.1)): + eslint-config-prettier@10.1.8(eslint@10.0.3(jiti@2.7.0)): dependencies: - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.0.3(jiti@2.7.0) eslint-import-context@0.1.9(unrs-resolver@1.11.1): dependencies: @@ -12292,10 +11377,10 @@ snapshots: optionalDependencies: unrs-resolver: 1.11.1 - eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1)))(eslint@10.0.3(jiti@2.6.1)): + eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3))(eslint@10.0.3(jiti@2.7.0)))(eslint@10.0.3(jiti@2.7.0)): dependencies: debug: 4.4.3 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.0.3(jiti@2.7.0) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) get-tsconfig: 4.13.6 is-bun-module: 2.0.0 @@ -12303,17 +11388,17 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import-x: 4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1)) + eslint-plugin-import-x: 4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3))(eslint@10.0.3(jiti@2.7.0)) transitivePeerDependencies: - supports-color - eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1)): + eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3))(eslint@10.0.3(jiti@2.7.0)): dependencies: '@package-json/types': 0.0.12 '@typescript-eslint/types': 8.56.1 comment-parser: 1.4.5 debug: 4.4.3 - eslint: 10.0.3(jiti@2.6.1) + eslint: 10.0.3(jiti@2.7.0) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) is-glob: 4.0.3 minimatch: 10.2.4 @@ -12321,14 +11406,14 @@ snapshots: stable-hash-x: 0.2.0 unrs-resolver: 1.11.1 optionalDependencies: - '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) transitivePeerDependencies: - supports-color - eslint-plugin-perfectionist@5.6.0(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3): + eslint-plugin-perfectionist@5.6.0(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - eslint: 10.0.3(jiti@2.6.1) + '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) + eslint: 10.0.3(jiti@2.7.0) natural-orderby: 5.0.0 transitivePeerDependencies: - supports-color @@ -12337,7 +11422,7 @@ snapshots: eslint-scope@9.1.2: dependencies: '@types/esrecurse': 4.3.1 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 esrecurse: 4.3.0 estraverse: 5.3.0 @@ -12345,9 +11430,9 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.0.3(jiti@2.6.1): + eslint@10.0.3(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.3 '@eslint/config-helpers': 0.5.3 @@ -12378,7 +11463,7 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: - jiti: 2.6.1 + jiti: 2.7.0 transitivePeerDependencies: - supports-color @@ -12402,7 +11487,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 esutils@2.0.3: {} @@ -12495,19 +11580,7 @@ snapshots: events@3.3.0: {} - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - expect-type@1.3.0: {} + expect-type@1.4.0: {} extendable-error@0.1.7: {} @@ -12577,6 +11650,8 @@ snapshots: follow-redirects@1.15.11: {} + follow-redirects@1.16.0: {} + for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -12589,10 +11664,10 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 - framer-motion@12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + framer-motion@12.42.2(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - motion-dom: 12.38.0 - motion-utils: 12.36.0 + motion-dom: 12.42.2 + motion-utils: 12.39.0 tslib: 2.8.1 optionalDependencies: '@emotion/is-prop-valid': 1.4.0 @@ -12616,7 +11691,7 @@ snapshots: function-bind@1.1.2: {} - fuse.js@7.1.0: {} + fuse.js@7.4.2: {} generator-function@2.0.1: {} @@ -12646,8 +11721,6 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 - get-stream@6.0.1: {} - get-tsconfig@4.13.6: dependencies: resolve-pkg-maps: 1.0.0 @@ -12685,16 +11758,16 @@ snapshots: graceful-fs@4.2.11: {} - h3@1.15.10: + h3@1.15.11: dependencies: - cookie-es: 1.2.2 + cookie-es: 1.2.3 crossws: 0.3.5 - defu: 6.1.4 + defu: 6.1.7 destr: 2.0.5 iron-webcrypto: 1.2.1 node-mock-http: 1.0.4 radix3: 1.1.2 - ufo: 1.6.3 + ufo: 1.6.4 uncrypto: 0.1.3 has-flag@4.0.0: {} @@ -12724,11 +11797,16 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - hono@4.12.9: {} + hono@4.12.27: {} - human-id@4.1.3: {} + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color - human-signals@2.1.0: {} + human-id@4.1.3: {} humanize-ms@1.2.1: dependencies: @@ -12736,23 +11814,16 @@ snapshots: husky@9.1.7: {} - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - optional: true - iconv-lite@0.7.2: dependencies: safer-buffer: 2.1.2 idb-keyval@6.2.1: {} - idb-keyval@6.2.2: {} + idb-keyval@6.2.6: {} idb@7.1.1: {} - idb@8.0.3: {} - ieee754@1.2.1: {} ignore@5.3.2: {} @@ -12772,8 +11843,6 @@ snapshots: inherits@2.0.4: {} - ini@1.3.8: {} - ini@4.1.1: {} ink-spinner@5.0.0(ink@5.2.1(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(utf-8-validate@6.0.6))(react@18.3.1): @@ -12832,8 +11901,6 @@ snapshots: is-callable@1.2.7: {} - is-docker@2.2.1: {} - is-docker@3.0.0: {} is-extglob@2.1.1: {} @@ -12870,8 +11937,6 @@ snapshots: is-plain-obj@4.1.0: {} - is-port-reachable@4.0.0: {} - is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -12889,14 +11954,10 @@ snapshots: is-typed-array@1.1.15: dependencies: - which-typed-array: 1.1.20 + which-typed-array: 1.1.22 is-windows@1.0.2: {} - is-wsl@2.2.0: - dependencies: - is-docker: 2.2.1 - is-wsl@3.1.1: dependencies: is-inside-container: 1.0.0 @@ -12907,17 +11968,17 @@ snapshots: isexe@2.0.0: {} - isomorphic-ws@4.0.1(ws@7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6)): + isomorphic-ws@4.0.1(ws@7.5.11(bufferutil@4.1.0)(utf-8-validate@6.0.6)): dependencies: - ws: 7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 7.5.11(bufferutil@4.1.0)(utf-8-validate@6.0.6) isows@1.0.6(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)): dependencies: ws: 8.18.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - isows@1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)): + isows@1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)): dependencies: - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) jayson@4.3.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): dependencies: @@ -12928,18 +11989,20 @@ snapshots: delay: 5.0.0 es6-promisify: 5.0.0 eyes: 0.1.8 - isomorphic-ws: 4.0.1(ws@7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + isomorphic-ws: 4.0.1(ws@7.5.11(bufferutil@4.1.0)(utf-8-validate@6.0.6)) json-stringify-safe: 5.0.1 stream-json: 1.9.1 uuid: 8.3.2 - ws: 7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 7.5.11(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - utf-8-validate jiti@2.6.1: {} - jose@6.2.2: {} + jiti@2.7.0: {} + + jose@6.2.3: {} js-base64@3.7.8: {} @@ -12947,6 +12010,8 @@ snapshots: js-tokens@4.0.0: {} + js-tokens@9.0.1: {} + js-yaml@3.14.2: dependencies: argparse: 1.0.10 @@ -12962,8 +12027,6 @@ snapshots: json-canonicalize@1.2.0: {} - json-canonicalize@2.0.0: {} - json-parse-even-better-errors@2.3.1: {} json-rpc-engine@6.1.0: @@ -13001,95 +12064,44 @@ snapshots: keyvaluestorage-interface@1.0.0: {} - kleur@4.1.5: {} - levn@0.4.1: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - lightningcss-android-arm64@1.31.1: - optional: true - lightningcss-android-arm64@1.32.0: optional: true - lightningcss-darwin-arm64@1.31.1: - optional: true - lightningcss-darwin-arm64@1.32.0: optional: true - lightningcss-darwin-x64@1.31.1: - optional: true - lightningcss-darwin-x64@1.32.0: optional: true - lightningcss-freebsd-x64@1.31.1: - optional: true - lightningcss-freebsd-x64@1.32.0: optional: true - lightningcss-linux-arm-gnueabihf@1.31.1: - optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: optional: true - lightningcss-linux-arm64-gnu@1.31.1: - optional: true - lightningcss-linux-arm64-gnu@1.32.0: optional: true - lightningcss-linux-arm64-musl@1.31.1: - optional: true - lightningcss-linux-arm64-musl@1.32.0: optional: true - lightningcss-linux-x64-gnu@1.31.1: - optional: true - lightningcss-linux-x64-gnu@1.32.0: optional: true - lightningcss-linux-x64-musl@1.31.1: - optional: true - lightningcss-linux-x64-musl@1.32.0: optional: true - lightningcss-win32-arm64-msvc@1.31.1: - optional: true - lightningcss-win32-arm64-msvc@1.32.0: optional: true - lightningcss-win32-x64-msvc@1.31.1: - optional: true - lightningcss-win32-x64-msvc@1.32.0: optional: true - lightningcss@1.31.1: - dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-android-arm64: 1.31.1 - lightningcss-darwin-arm64: 1.31.1 - lightningcss-darwin-x64: 1.31.1 - lightningcss-freebsd-x64: 1.31.1 - lightningcss-linux-arm-gnueabihf: 1.31.1 - lightningcss-linux-arm64-gnu: 1.31.1 - lightningcss-linux-arm64-musl: 1.31.1 - lightningcss-linux-x64-gnu: 1.31.1 - lightningcss-linux-x64-musl: 1.31.1 - lightningcss-win32-arm64-msvc: 1.31.1 - lightningcss-win32-x64-msvc: 1.31.1 - lightningcss@1.32.0: dependencies: detect-libc: 2.1.2 @@ -13128,11 +12140,11 @@ snapshots: lit-element@4.2.2: dependencies: - '@lit-labs/ssr-dom-shim': 1.5.1 + '@lit-labs/ssr-dom-shim': 1.6.0 '@lit/reactive-element': 2.1.2 - lit-html: 3.3.2 + lit-html: 3.3.3 - lit-html@3.3.2: + lit-html@3.3.3: dependencies: '@types/trusted-types': 2.0.7 @@ -13140,7 +12152,7 @@ snapshots: dependencies: '@lit/reactive-element': 2.1.2 lit-element: 4.2.2 - lit-html: 3.3.2 + lit-html: 3.3.3 locate-path@5.0.0: dependencies: @@ -13162,7 +12174,7 @@ snapshots: lodash.upperfirst@4.3.1: {} - lodash@4.17.23: {} + lodash@4.18.1: {} log-update@6.1.0: dependencies: @@ -13178,7 +12190,7 @@ snapshots: loupe@3.2.1: {} - lru-cache@11.2.7: {} + lru-cache@11.5.1: {} lru-cache@5.1.1: dependencies: @@ -13208,8 +12220,6 @@ snapshots: meow@13.2.0: {} - merge-stream@2.0.0: {} - merge2@1.4.1: {} micro-ftch@0.3.1: {} @@ -13219,16 +12229,8 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - mime-db@1.33.0: {} - mime-db@1.52.0: {} - mime-db@1.54.0: {} - - mime-types@2.1.18: - dependencies: - mime-db: 1.33.0 - mime-types@2.1.35: dependencies: mime-db: 1.52.0 @@ -13237,18 +12239,6 @@ snapshots: mimic-function@5.0.1: {} - miniflare@4.20260305.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - sharp: 0.34.5 - undici: 7.18.2 - workerd: 1.20260305.0 - ws: 8.18.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - youch: 4.1.0-beta.10 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - minimalistic-assert@1.0.1: {} minimalistic-crypto-utils@1.0.1: {} @@ -13257,25 +12247,21 @@ snapshots: dependencies: brace-expansion: 5.0.4 - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.12 - minimist@1.2.8: {} mipd@0.0.7(typescript@5.9.3): optionalDependencies: typescript: 5.9.3 - motion-dom@12.38.0: + motion-dom@12.42.2: dependencies: - motion-utils: 12.36.0 + motion-utils: 12.39.0 - motion-utils@12.36.0: {} + motion-utils@12.39.0: {} motion@12.34.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - framer-motion: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + framer-motion: 12.42.2(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tslib: 2.8.1 optionalDependencies: '@emotion/is-prop-valid': 1.4.0 @@ -13284,8 +12270,6 @@ snapshots: mri@1.2.0: {} - ms@2.0.0: {} - ms@2.1.2: {} ms@2.1.3: {} @@ -13300,19 +12284,15 @@ snapshots: natural-orderby@5.0.0: {} - negotiator@0.6.4: {} - node-addon-api@2.0.2: {} node-addon-api@7.1.1: {} node-fetch-native@1.6.7: {} - node-fetch@2.7.0(encoding@0.1.13): + node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 - optionalDependencies: - encoding: 0.1.13 node-gyp-build@4.8.4: {} @@ -13322,10 +12302,6 @@ snapshots: normalize-path@3.0.0: {} - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - obj-multiplex@1.0.0: dependencies: end-of-stream: 1.4.5 @@ -13336,12 +12312,10 @@ snapshots: dependencies: destr: 2.0.5 node-fetch-native: 1.6.7 - ufo: 1.6.3 + ufo: 1.6.4 on-exit-leak-free@0.2.0: {} - on-headers@1.1.0: {} - once@1.4.0: dependencies: wrappy: 1.0.2 @@ -13378,7 +12352,7 @@ snapshots: outdent@0.5.0: {} - ox@0.11.3(typescript@5.9.3)(zod@3.25.76): + ox@0.13.1(typescript@5.9.3)(zod@3.25.76): dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 @@ -13393,7 +12367,7 @@ snapshots: transitivePeerDependencies: - zod - ox@0.12.4(typescript@5.9.3)(zod@3.22.4): + ox@0.14.29(typescript@5.9.3)(zod@3.22.4): dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 @@ -13408,7 +12382,7 @@ snapshots: transitivePeerDependencies: - zod - ox@0.12.4(typescript@5.9.3)(zod@3.25.76): + ox@0.14.29(typescript@5.9.3)(zod@3.25.76): dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 @@ -13423,7 +12397,7 @@ snapshots: transitivePeerDependencies: - zod - ox@0.12.4(typescript@5.9.3)(zod@4.3.6): + ox@0.14.29(typescript@5.9.3)(zod@4.3.6): dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 @@ -13438,21 +12412,6 @@ snapshots: transitivePeerDependencies: - zod - ox@0.13.1(typescript@5.9.3)(zod@3.25.76): - dependencies: - '@adraffy/ens-normalize': 1.11.1 - '@noble/ciphers': 1.3.0 - '@noble/curves': 1.9.7 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 - abitype: 1.2.3(typescript@5.9.3)(zod@3.25.76) - eventemitter3: 5.0.1 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - zod - ox@0.6.7(typescript@5.9.3)(zod@3.25.76): dependencies: '@adraffy/ens-normalize': 1.11.1 @@ -13554,14 +12513,8 @@ snapshots: path-exists@4.0.0: {} - path-is-inside@1.0.2: {} - path-key@3.1.1: {} - path-to-regexp@3.3.0: {} - - path-to-regexp@6.3.0: {} - path-type@4.0.0: {} pathe@2.0.3: {} @@ -13601,34 +12554,25 @@ snapshots: sonic-boom: 2.8.0 thread-stream: 0.15.2 - pkijs@3.3.3: - dependencies: - '@noble/hashes': 1.8.0 - asn1js: 3.0.7 - bytestreamjs: 2.0.1 - pvtsutils: 1.3.6 - pvutils: 1.1.5 - tslib: 2.8.1 - pngjs@5.0.0: {} pony-cause@2.1.11: {} - porto@0.2.35(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(@wagmi/core@2.22.1(@tanstack/query-core@5.95.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)): + porto@0.2.35(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76)): dependencies: - '@wagmi/core': 2.22.1(@tanstack/query-core@5.95.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) - hono: 4.12.9 - idb-keyval: 6.2.2 + '@wagmi/core': 2.22.1(@tanstack/query-core@5.101.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + hono: 4.12.27 + idb-keyval: 6.2.6 mipd: 0.0.7(typescript@5.9.3) ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) zod: 4.3.6 - zustand: 5.0.12(@types/react@18.3.28)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)) + zustand: 5.0.14(@types/react@18.3.28)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)) optionalDependencies: - '@tanstack/react-query': 5.95.2(react@18.3.1) + '@tanstack/react-query': 5.101.2(react@18.3.1) react: 18.3.1 typescript: 5.9.3 - wagmi: 2.19.5(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76) + wagmi: 2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76) transitivePeerDependencies: - '@types/react' - immer @@ -13644,7 +12588,7 @@ snapshots: preact@10.24.2: {} - preact@10.29.0: {} + preact@10.29.4: {} prelude-ls@1.2.1: {} @@ -13660,6 +12604,8 @@ snapshots: proxy-from-env@1.1.0: {} + proxy-from-env@2.1.0: {} + pump@3.0.4: dependencies: end-of-stream: 1.4.5 @@ -13667,12 +12613,6 @@ snapshots: punycode@2.3.1: {} - pvtsutils@1.3.6: - dependencies: - tslib: 2.8.1 - - pvutils@1.1.5: {} - qrcode@1.5.3: dependencies: dijkstrajs: 1.0.3 @@ -13701,16 +12641,7 @@ snapshots: radix3@1.1.2: {} - range-parser@1.2.0: {} - - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - - react-apple-signin-auth@1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-apple-signin-auth@1.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13721,7 +12652,7 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-hook-form@7.72.0(react@18.3.1): + react-hook-form@7.81.0(react@18.3.1): dependencies: react: 18.3.1 @@ -13791,15 +12722,6 @@ snapshots: real-require@0.1.0: {} - registry-auth-token@3.3.2: - dependencies: - rc: 1.2.8 - safe-buffer: 5.2.1 - - registry-url@3.1.0: - dependencies: - rc: 1.2.8 - require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -13826,46 +12748,46 @@ snapshots: rfdc@1.4.1: {} - rollup@4.59.0: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.59.0 - '@rollup/rollup-android-arm64': 4.59.0 - '@rollup/rollup-darwin-arm64': 4.59.0 - '@rollup/rollup-darwin-x64': 4.59.0 - '@rollup/rollup-freebsd-arm64': 4.59.0 - '@rollup/rollup-freebsd-x64': 4.59.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 - '@rollup/rollup-linux-arm-musleabihf': 4.59.0 - '@rollup/rollup-linux-arm64-gnu': 4.59.0 - '@rollup/rollup-linux-arm64-musl': 4.59.0 - '@rollup/rollup-linux-loong64-gnu': 4.59.0 - '@rollup/rollup-linux-loong64-musl': 4.59.0 - '@rollup/rollup-linux-ppc64-gnu': 4.59.0 - '@rollup/rollup-linux-ppc64-musl': 4.59.0 - '@rollup/rollup-linux-riscv64-gnu': 4.59.0 - '@rollup/rollup-linux-riscv64-musl': 4.59.0 - '@rollup/rollup-linux-s390x-gnu': 4.59.0 - '@rollup/rollup-linux-x64-gnu': 4.59.0 - '@rollup/rollup-linux-x64-musl': 4.59.0 - '@rollup/rollup-openbsd-x64': 4.59.0 - '@rollup/rollup-openharmony-arm64': 4.59.0 - '@rollup/rollup-win32-arm64-msvc': 4.59.0 - '@rollup/rollup-win32-ia32-msvc': 4.59.0 - '@rollup/rollup-win32-x64-gnu': 4.59.0 - '@rollup/rollup-win32-x64-msvc': 4.59.0 + rollup@4.62.2: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.2 + '@rollup/rollup-android-arm64': 4.62.2 + '@rollup/rollup-darwin-arm64': 4.62.2 + '@rollup/rollup-darwin-x64': 4.62.2 + '@rollup/rollup-freebsd-arm64': 4.62.2 + '@rollup/rollup-freebsd-x64': 4.62.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 + '@rollup/rollup-linux-arm-musleabihf': 4.62.2 + '@rollup/rollup-linux-arm64-gnu': 4.62.2 + '@rollup/rollup-linux-arm64-musl': 4.62.2 + '@rollup/rollup-linux-loong64-gnu': 4.62.2 + '@rollup/rollup-linux-loong64-musl': 4.62.2 + '@rollup/rollup-linux-ppc64-gnu': 4.62.2 + '@rollup/rollup-linux-ppc64-musl': 4.62.2 + '@rollup/rollup-linux-riscv64-gnu': 4.62.2 + '@rollup/rollup-linux-riscv64-musl': 4.62.2 + '@rollup/rollup-linux-s390x-gnu': 4.62.2 + '@rollup/rollup-linux-x64-gnu': 4.62.2 + '@rollup/rollup-linux-x64-musl': 4.62.2 + '@rollup/rollup-openbsd-x64': 4.62.2 + '@rollup/rollup-openharmony-arm64': 4.62.2 + '@rollup/rollup-win32-arm64-msvc': 4.62.2 + '@rollup/rollup-win32-ia32-msvc': 4.62.2 + '@rollup/rollup-win32-x64-gnu': 4.62.2 + '@rollup/rollup-win32-x64-msvc': 4.62.2 fsevents: 2.3.3 - rpc-websockets@9.3.7: + rpc-websockets@9.3.9: dependencies: - '@swc/helpers': 0.5.20 + '@swc/helpers': 0.5.23 '@types/uuid': 10.0.0 '@types/ws': 8.18.1 buffer: 6.0.3 eventemitter3: 5.0.1 - uuid: 11.1.0 - ws: 8.20.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + uuid: 14.0.1 + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: bufferutil: 4.1.0 utf-8-validate: 6.0.6 @@ -13904,32 +12826,6 @@ snapshots: semver@7.7.4: {} - serve-handler@6.1.6: - dependencies: - bytes: 3.0.0 - content-disposition: 0.5.2 - mime-types: 2.1.18 - minimatch: 3.1.2 - path-is-inside: 1.0.2 - path-to-regexp: 3.3.0 - range-parser: 1.2.0 - - serve@14.2.5: - dependencies: - '@zeit/schemas': 2.36.0 - ajv: 8.12.0 - arg: 5.0.2 - boxen: 7.0.0 - chalk: 5.0.1 - chalk-template: 0.4.0 - clipboardy: 3.0.0 - compression: 1.8.1 - is-port-reachable: 4.0.0 - serve-handler: 6.1.6 - update-check: 1.5.4 - transitivePeerDependencies: - - supports-color - set-blocking@2.0.0: {} set-function-length@1.2.2: @@ -13947,37 +12843,6 @@ snapshots: safe-buffer: 5.2.1 to-buffer: 1.2.2 - sharp@0.34.5: - dependencies: - '@img/colour': 1.1.0 - detect-libc: 2.1.2 - semver: 7.7.4 - optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.5 - '@img/sharp-darwin-x64': 0.34.5 - '@img/sharp-libvips-darwin-arm64': 1.2.4 - '@img/sharp-libvips-darwin-x64': 1.2.4 - '@img/sharp-libvips-linux-arm': 1.2.4 - '@img/sharp-libvips-linux-arm64': 1.2.4 - '@img/sharp-libvips-linux-ppc64': 1.2.4 - '@img/sharp-libvips-linux-riscv64': 1.2.4 - '@img/sharp-libvips-linux-s390x': 1.2.4 - '@img/sharp-libvips-linux-x64': 1.2.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - '@img/sharp-linux-arm': 0.34.5 - '@img/sharp-linux-arm64': 0.34.5 - '@img/sharp-linux-ppc64': 0.34.5 - '@img/sharp-linux-riscv64': 0.34.5 - '@img/sharp-linux-s390x': 0.34.5 - '@img/sharp-linux-x64': 0.34.5 - '@img/sharp-linuxmusl-arm64': 0.34.5 - '@img/sharp-linuxmusl-x64': 0.34.5 - '@img/sharp-wasm32': 0.34.5 - '@img/sharp-win32-arm64': 0.34.5 - '@img/sharp-win32-ia32': 0.34.5 - '@img/sharp-win32-x64': 0.34.5 - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -14021,7 +12886,7 @@ snapshots: dependencies: '@socket.io/component-emitter': 3.1.2 debug: 4.4.3 - engine.io-client: 6.6.4(bufferutil@4.1.0)(utf-8-validate@6.0.6) + engine.io-client: 6.6.6(bufferutil@4.1.0)(utf-8-validate@6.0.6) socket.io-parser: 4.2.6 transitivePeerDependencies: - bufferutil @@ -14089,12 +12954,6 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.2.0 - string-width@7.2.0: dependencies: emoji-regex: 10.6.0 @@ -14124,16 +12983,14 @@ snapshots: strip-bom@3.0.0: {} - strip-final-newline@2.0.0: {} - - strip-json-comments@2.0.1: {} + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 superstruct@1.0.4: {} superstruct@2.0.2: {} - supports-color@10.2.2: {} - supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -14142,13 +12999,11 @@ snapshots: dependencies: has-flag: 4.0.0 - tailwind-merge@3.5.0: {} + tailwind-merge@3.6.0: {} - tailwindcss@4.2.1: {} + tailwindcss@4.3.2: {} - tailwindcss@4.2.2: {} - - tapable@2.3.0: {} + tapable@2.3.3: {} term-size@2.2.1: {} @@ -14181,7 +13036,7 @@ snapshots: tinyrainbow@2.0.0: {} - tinyspy@3.0.2: {} + tinyspy@4.0.4: {} to-buffer@1.2.2: dependencies: @@ -14214,19 +13069,12 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - tweetnacl-sealedbox-js@1.2.0: - dependencies: - blakejs: 1.2.1 - tweetnacl: 1.0.3 - tweetnacl@1.0.3: {} type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - type-fest@2.19.0: {} - type-fest@4.41.0: {} typed-array-buffer@1.0.3: @@ -14235,20 +13083,20 @@ snapshots: es-errors: 1.3.0 is-typed-array: 1.1.15 - typescript-eslint@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3))(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) - eslint: 10.0.3(jiti@2.6.1) + '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.7.0))(typescript@5.9.3) + eslint: 10.0.3(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color typescript@5.9.3: {} - ufo@1.6.3: {} + ufo@1.6.4: {} uint8arrays@3.1.0: dependencies: @@ -14260,18 +13108,7 @@ snapshots: undici-types@6.21.0: {} - undici-types@7.18.2: - optional: true - - undici-types@7.24.6: {} - - undici@7.18.2: {} - - undici@7.22.0: {} - - unenv@2.0.0-rc.24: - dependencies: - pathe: 2.0.3 + undici-types@7.28.0: {} universalify@0.1.2: {} @@ -14299,18 +13136,18 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - unstorage@1.17.5(idb-keyval@6.2.2): + unstorage@1.17.5(idb-keyval@6.2.6): dependencies: anymatch: 3.1.3 chokidar: 5.0.0 destr: 2.0.5 - h3: 1.15.10 - lru-cache: 11.2.7 + h3: 1.15.11 + lru-cache: 11.5.1 node-fetch-native: 1.6.7 ofetch: 1.5.1 - ufo: 1.6.3 + ufo: 1.6.4 optionalDependencies: - idb-keyval: 6.2.2 + idb-keyval: 6.2.6 update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: @@ -14318,11 +13155,6 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - update-check@1.5.4: - dependencies: - registry-auth-token: 3.3.2 - registry-url: 3.1.0 - uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -14367,13 +13199,11 @@ snapshots: is-arguments: 1.2.0 is-generator-function: 1.1.2 is-typed-array: 1.1.15 - which-typed-array: 1.1.20 + which-typed-array: 1.1.22 uuid@10.0.0: {} - uuid@11.1.0: {} - - uuid@13.0.0: {} + uuid@14.0.1: {} uuid@8.3.2: {} @@ -14390,8 +13220,6 @@ snapshots: '@types/react': 18.3.28 react: 18.3.1 - vary@1.1.2: {} - viem@2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76): dependencies: '@noble/curves': 1.9.7 @@ -14409,16 +13237,16 @@ snapshots: - utf-8-validate - zod - viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.22.4): + viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.22.4): dependencies: '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@5.9.3)(zod@3.22.4) - isows: 1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - ox: 0.12.4(typescript@5.9.3)(zod@3.22.4) - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + isows: 1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + ox: 0.14.29(typescript@5.9.3)(zod@3.22.4) + ws: 8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -14426,16 +13254,16 @@ snapshots: - utf-8-validate - zod - viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76): + viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76): dependencies: '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@5.9.3)(zod@3.25.76) - isows: 1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - ox: 0.12.4(typescript@5.9.3)(zod@3.25.76) - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + isows: 1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + ox: 0.14.29(typescript@5.9.3)(zod@3.25.76) + ws: 8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -14443,16 +13271,16 @@ snapshots: - utf-8-validate - zod - viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6): + viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@4.3.6): dependencies: '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@5.9.3)(zod@4.3.6) - isows: 1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - ox: 0.12.4(typescript@5.9.3)(zod@4.3.6) - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + isows: 1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + ox: 0.14.29(typescript@5.9.3)(zod@4.3.6) + ws: 8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -14460,13 +13288,13 @@ snapshots: - utf-8-validate - zod - vite-node@3.1.4(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1): + vite-node@3.2.4(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1) + vite: 5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) transitivePeerDependencies: - '@types/node' - less @@ -14478,43 +13306,45 @@ snapshots: - supports-color - terser - vite@5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1): + vite@5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1): dependencies: esbuild: 0.21.5 postcss: 8.5.6 - rollup: 4.59.0 + rollup: 4.62.2 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 22.19.13 fsevents: 2.3.3 lightningcss: 1.32.0 terser: 5.46.1 - vitest@3.1.4(@types/debug@4.1.13)(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1): + vitest@3.2.7(@types/debug@4.1.13)(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1): dependencies: - '@vitest/expect': 3.1.4 - '@vitest/mocker': 3.1.4(vite@5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1)) - '@vitest/pretty-format': 3.2.4 - '@vitest/runner': 3.1.4 - '@vitest/snapshot': 3.1.4 - '@vitest/spy': 3.1.4 - '@vitest/utils': 3.1.4 + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.7 + '@vitest/mocker': 3.2.7(vite@5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1)) + '@vitest/pretty-format': 3.2.7 + '@vitest/runner': 3.2.7 + '@vitest/snapshot': 3.2.7 + '@vitest/spy': 3.2.7 + '@vitest/utils': 3.2.7 chai: 5.3.3 debug: 4.4.3 - expect-type: 1.3.0 + expect-type: 1.4.0 magic-string: 0.30.21 pathe: 2.0.3 + picomatch: 4.0.3 std-env: 3.10.0 tinybench: 2.9.0 tinyexec: 0.3.2 tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 5.4.21(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1) - vite-node: 3.1.4(@types/node@25.3.3)(lightningcss@1.32.0)(terser@5.46.1) + vite: 5.4.21(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) + vite-node: 3.2.4(@types/node@22.19.13)(lightningcss@1.32.0)(terser@5.46.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.13 - '@types/node': 25.3.3 + '@types/node': 22.19.13 transitivePeerDependencies: - less - lightningcss @@ -14526,14 +13356,14 @@ snapshots: - supports-color - terser - wagmi@2.19.5(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76): + wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76): dependencies: - '@tanstack/react-query': 5.95.2(react@18.3.1) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(@wagmi/core@2.22.1(@tanstack/query-core@5.95.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.95.2)(@tanstack/react-query@5.95.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(encoding@0.1.13)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.95.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) + '@tanstack/react-query': 5.101.2(react@18.3.1) + '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(@wagmi/core@2.22.1(@tanstack/query-core@5.101.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)))(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.101.2)(@tanstack/react-query@5.101.2(react@18.3.1))(@types/react@18.3.28)(bufferutil@4.1.0)(react@18.3.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.101.2)(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76)) react: 18.3.1 use-sync-external-store: 1.4.0(react@18.3.1) - viem: 2.46.3(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) + viem: 2.53.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)(zod@3.25.76) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -14582,10 +13412,10 @@ snapshots: which-module@2.0.1: {} - which-typed-array@1.1.20: + which-typed-array@1.1.22: dependencies: available-typed-arrays: 1.0.7 - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 for-each: 0.3.5 get-proto: 1.0.1 @@ -14601,41 +13431,12 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 - widest-line@4.0.1: - dependencies: - string-width: 5.1.2 - widest-line@5.0.0: dependencies: string-width: 7.2.0 word-wrap@1.2.5: {} - workerd@1.20260305.0: - optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20260305.0 - '@cloudflare/workerd-darwin-arm64': 1.20260305.0 - '@cloudflare/workerd-linux-64': 1.20260305.0 - '@cloudflare/workerd-linux-arm64': 1.20260305.0 - '@cloudflare/workerd-windows-64': 1.20260305.0 - - wrangler@4.69.0(@cloudflare/workers-types@4.20260317.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6): - dependencies: - '@cloudflare/kv-asset-handler': 0.4.2 - '@cloudflare/unenv-preset': 2.14.0(unenv@2.0.0-rc.24)(workerd@1.20260305.0) - blake3-wasm: 2.1.5 - esbuild: 0.27.3 - miniflare: 4.20260305.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) - path-to-regexp: 6.3.0 - unenv: 2.0.0-rc.24 - workerd: 1.20260305.0 - optionalDependencies: - '@cloudflare/workers-types': 4.20260317.1 - fsevents: 2.3.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 @@ -14648,12 +13449,6 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 5.1.2 - strip-ansi: 7.2.0 - wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 @@ -14662,7 +13457,7 @@ snapshots: wrappy@1.0.2: {} - ws@7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6): + ws@7.5.11(bufferutil@4.1.0)(utf-8-validate@6.0.6): optionalDependencies: bufferutil: 4.1.0 utf-8-validate: 6.0.6 @@ -14677,12 +13472,17 @@ snapshots: bufferutil: 4.1.0 utf-8-validate: 6.0.6 - ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6): + ws@8.20.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): + optionalDependencies: + bufferutil: 4.1.0 + utf-8-validate: 6.0.6 + + ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6): optionalDependencies: bufferutil: 4.1.0 utf-8-validate: 6.0.6 - ws@8.20.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): + ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): optionalDependencies: bufferutil: 4.1.0 utf-8-validate: 6.0.6 @@ -14710,8 +13510,6 @@ snapshots: yargs-parser@21.1.1: {} - yargs-parser@22.0.0: {} - yargs@15.4.1: dependencies: cliui: 6.0.0 @@ -14736,32 +13534,10 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yargs@18.0.0: - dependencies: - cliui: 9.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - string-width: 7.2.0 - y18n: 5.0.8 - yargs-parser: 22.0.0 - yocto-queue@0.1.0: {} yoga-layout@3.2.1: {} - youch-core@0.3.3: - dependencies: - '@poppinss/exception': 1.2.3 - error-stack-parser-es: 1.0.5 - - youch@4.1.0-beta.10: - dependencies: - '@poppinss/colors': 4.1.6 - '@poppinss/dumper': 0.6.5 - '@speed-highlight/core': 1.2.14 - cookie: 1.1.1 - youch-core: 0.3.3 - zod@3.22.4: {} zod@3.25.76: {} @@ -14774,7 +13550,7 @@ snapshots: react: 18.3.1 use-sync-external-store: 1.4.0(react@18.3.1) - zustand@5.0.12(@types/react@18.3.28)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)): + zustand@5.0.14(@types/react@18.3.28)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)): optionalDependencies: '@types/react': 18.3.28 react: 18.3.1 diff --git a/skills/SKILL.md b/skills/SKILL.md index fb425df..9a5bf6e 100644 --- a/skills/SKILL.md +++ b/skills/SKILL.md @@ -1,53 +1,61 @@ --- name: Polygon Agent -description: "Complete Polygon agent toolkit for on-chain operations on Polygon. Use this skill whenever helping an agent set up a wallet, check balances, send or swap tokens, bridge assets, deposit or withdraw from yield (Aave aTokens, ERC-4626 vaults), register on-chain identity, submit or query reputation/feedback, or make x402 micropayments. Covers the full lifecycle: Sequence smart contract wallets, Trails DeFi actions, ERC-8004 identity + reputation, x402 payments. Single CLI entry point (`polygon-agent`), AES-256-GCM encrypted storage." +description: "Complete Polygon agent toolkit for on-chain operations on Polygon. Use this skill whenever helping an agent set up a wallet, check balances, send or swap tokens, bridge assets, deposit or withdraw from yield (Aave aTokens, ERC-4626 vaults), register on-chain identity, submit or query reputation/feedback, or make x402 micropayments. Covers the full lifecycle: OMS smart contract wallets, Trails DeFi actions, ERC-8004 identity + reputation, x402 payments. Single CLI entry point (`agent`), AES-256-GCM encrypted storage." --- # Polygon Agentic CLI ## Prerequisites -- Node.js 20+ +- Node.js 22+ - Install globally: `npm install -g @polygonlabs/agent-cli` (reinstall to update) -- Entry point: `polygon-agent ` +- Entry point: `agent ` - Storage: `~/.polygon-agent/` (AES-256-GCM encrypted) -> **Note for the agent: on first install, tell the user this is a global npm install** — installs the `polygon-agent` CLI system-wide so it runs from any terminal, may need sudo on some setups, re-running the same command updates it, and `npm uninstall -g @polygonlabs/agent-cli` removes it. Mention once on first install. +> **Note for the agent: on first install, tell the user this is a global npm install** — installs the `agent` CLI system-wide so it runs from any terminal, may need sudo on some setups, re-running the same command updates it, and `npm uninstall -g @polygonlabs/agent-cli` removes it. Mention once on first install. ## If a command fails with "Unknown argument" or "command not found" This skill is versioned with the CLI — commands and flags drift across releases. Check your version, compare to latest, and upgrade if behind: ```bash -polygon-agent --version # currently installed +agent --version # currently installed npm view @polygonlabs/agent-cli version # latest published npm install -g @polygonlabs/agent-cli@latest # upgrade ``` ## Architecture +The CLI uses the **OMS (Open Money Stack) V3 embedded-wallet** model (`@polygonlabs/oms-wallet`). By default, `wallet login` opens the agentconnect login page (`POLYGON_AGENT_LOGIN_UI`, default `https://agentconnect.polygon.technology`), where the user chooses Google or email (email sends a 6-digit code to the user's inbox, entered on the page). This works whether the browser is on this machine or a different one, so there is no separate headless mode. `--local` falls back to the legacy loopback flow (raw Google sign-in URL plus a localhost callback; browser must be on this same machine; Google only). `--remote` is deprecated and is now a no-op that prints a notice. Once the user signs in, the wallet is created or unlocked and the session credential is stored encrypted on disk. There is no on-chain permission scoping. + | Wallet | Created by | Purpose | Fund? | |--------|-----------|---------|-------| -| EOA | `setup` | Auth with Sequence Builder | NO | -| Ecosystem Wallet | `wallet create` | Primary spending wallet | YES | +| Embedded wallet (V3) | `wallet login` | Primary spending wallet | YES | + +The wallet address is the **same across all EVM chains**. Sessions last ~1 week before re-login is needed. ## Environment Variables -### Access key — one key, many names +### OMS credentials (optional) -`SEQUENCE_PROJECT_ACCESS_KEY`, `SEQUENCE_INDEXER_ACCESS_KEY`, and `TRAILS_API_KEY` are **all the same key** — the Sequence project access key created during `setup`. The CLI treats them as aliases and falls back through all of them automatically. +No setup step is required. The CLI ships a default OMS publishable key, and `wallet login` automatically provisions a dedicated Builder project and access key on first login, saving it to `~/.polygon-agent/builder.json`. -After `setup` runs the key is stored in `~/.polygon-agent/builder.json`. Every CLI invocation bootstraps it into the environment — no `export` is needed. In a fresh agent session with no environment variables set, simply run commands and the CLI reads credentials from disk. +| Variable | Description | +|----------|-------------| +| `OMS_PUBLISHABLE_KEY` | Advanced override: point at your own OMS Builder project instead of the default | -Only set these manually to override the stored value (e.g. to point at a different project): +Set it via env, or persist once with `setup` so every command reads it from `~/.polygon-agent/builder.json`: ```bash -export SEQUENCE_PROJECT_ACCESS_KEY= # also covers TRAILS_API_KEY and indexer calls +agent setup --oms-publishable-key ``` +`--oms-project-id ` is also accepted but optional — it's kept only as legacy display metadata. Plain `setup` (no key) still works for manual or `--force` re-provisioning. + ### Optional overrides | Variable | Default | |----------|---------| -| `SEQUENCE_ECOSYSTEM_CONNECTOR_URL` | `https://agentconnect.polygon.technology` | -| `SEQUENCE_DAPP_ORIGIN` | Same as connector URL origin | +| `POLYGON_AGENT_LOGIN_UI` | Base URL of the browser login page opened by `wallet login` (default `https://agentconnect.polygon.technology`) | +| `POLYGON_AGENT_OIDC_RELAY` | Base URL of the OIDC relay used by `wallet login` (default `https://oidc-relay.polygon.technology`); also settable per run with `--relay-url` | +| `SEQUENCE_PROJECT_ACCESS_KEY` | Used only as the Trails API key for DeFi earn-pool lookups (optional) | | `TRAILS_TOKEN_MAP_JSON` | Token-directory lookup | | `POLYGON_AGENT_DEBUG_FETCH` | Off — logs HTTP to `~/.polygon-agent/fetch-debug.log` | | `POLYGON_AGENT_DEBUG_FEE` | Off — dumps fee options to stderr | @@ -55,38 +63,30 @@ export SEQUENCE_PROJECT_ACCESS_KEY= # also covers TRAILS_API_KEY and index ## Complete Setup Flow ```bash -# Step 1: Setup (creates EOA + Sequence project, stores access key to disk) -polygon-agent setup --name "MyAgent" -# → saves privateKey (not shown again), eoaAddress, accessKey to ~/.polygon-agent/builder.json -# → all subsequent commands auto-load the access key from disk — no export needed - -# Step 2: Create ecosystem wallet (opens browser, waits for 6-digit code) -# Aave V3 Pool is auto-whitelisted in all sessions. For Morpho or other DeFi vaults, -# add --contract flags as needed. -polygon-agent wallet create --usdc-limit 50 --native-limit 5 \ - --contract 0xc2132D05D31c914a87C6611C10748AEb04B58e8F \ - --contract 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619 \ - --contract 0x781fb7f6d845e3be129289833b04d43aa8558c42 \ - --contract 0xf5c81d25ee174d83f1fd202ca94ae6070d073ccf \ - --contract 0x3f33f9f7e2d7cfbcbdf8ea8b870a6e3d449664c2 -# → opens https://agentconnect.polygon.technology/link?rid=&... -# → user approves in browser, browser shows a 6-digit code -# → enter the 6-digit code in the terminal when prompted -# → session saved to ~/.polygon-agent/wallets/main.json -# → notify the user and send them to https://agentconnect.polygon.technology/?rid= -# so they can fund their wallet with access to the session - -# Step 3: Fund wallet -polygon-agent fund -# → reads walletAddress from session, builds Trails widget URL with toAddress= +# Step 1: Log in in the browser +agent wallet login +# → opens the agentconnect login page; choose Google or email (email sends +# a 6-digit code to the user's inbox, entered on the page) +# → works whether the browser is on this machine or elsewhere, so there is +# no separate headless mode +# → --local falls back to the legacy loopback flow (Google only, browser +# must be on this machine) +# → session saved to ~/.polygon-agent/oms/main/; prints the walletAddress +# → no setup step needed: the CLI ships a default OMS publishable key, and +# login auto-provisions a Builder project + access key to +# ~/.polygon-agent/builder.json + +# Step 2: Fund wallet +agent fund +# → reads walletAddress from the session, builds the Trails widget URL with toAddress= # → ALWAYS run this command to get the URL — never construct it manually or hardcode any address # → send the returned `fundingUrl` to the user; `walletAddress` in the output confirms the recipient -# Step 4: Verify balances -polygon-agent balances +# Step 3: Verify balances +agent balances -# Step 5: Register agent on-chain (ERC-8004, Polygon mainnet only) -polygon-agent agent register --name "MyAgent" --broadcast +# Step 4: Register agent on-chain (ERC-8004, Polygon mainnet only) +agent agent register --name "MyAgent" --broadcast # → mints ERC-721 NFT, emits Registered event containing agentId # → retrieve agentId: open the tx on https://polygonscan.com, go to Logs tab, # find the Registered event — agentId is the first indexed parameter @@ -103,11 +103,11 @@ For specific workflows, fetch and load the relevant sub-skill **before attemptin | DeFi — swap, deposit, withdraw, yield | https://agentconnect.polygon.technology/polygon-defi/SKILL.md | | x402 discovery & pay-per-call APIs | https://agentconnect.polygon.technology/polygon-discovery/SKILL.md | -> **IMPORTANT — x402 calls:** If the user asks to use x402 to fetch data (Twitter/X profiles, web search, news, AI images, code review, etc.), follow these steps in order before making any request: +> **IMPORTANT — x402 calls:** If the user asks to use x402 to fetch data or call a service (web search, scraping, news, LLM inference, email, on-chain wallet analytics, multi-chain RPC, etc.), follow these steps in order before making any request: > > 1. Fetch and read the discovery skill: `GET https://agentconnect.polygon.technology/polygon-discovery/SKILL.md` -> 2. Run `polygon-agent wallet list` — if no wallet exists, run through the wallet creation flow: `polygon-agent setup` (if not already done), then `polygon-agent wallet create` to open a browser session and establish a secure encrypted wallet session. Enter the 6-digit code when prompted, then fund the wallet before continuing. -> 3. Run `polygon-agent balances` — confirm USDC is available before proceeding; x402 calls will fail with an EOA funding error if the wallet is empty +> 2. Run `agent wallet list` — if no wallet exists, log in: `agent wallet login` and sign in on the login page (Google or email), then fund the wallet before continuing. No setup step is needed first. +> 3. Run `agent balances` — confirm USDC is available before proceeding; x402 calls will fail with an EOA funding error if the wallet is empty > > Do not guess endpoints or search the web for x402 providers. The discovery skill documents the correct, working endpoints with exact URL formats. @@ -117,46 +117,44 @@ For specific workflows, fetch and load the relevant sub-skill **before attemptin ### Setup ```bash -polygon-agent setup --name [--force] +agent setup [--name ] [--force] + [--oms-publishable-key ] [--oms-project-id ] # save OMS credentials (project id optional/legacy) ``` ### Wallet -Valid `--chain` values: `polygon` (default/mainnet), `amoy` (Polygon testnet), `mainnet` (Ethereum), `arbitrum`, `optimism`, `base`. ERC-8004 agent operations only support `polygon`. +Valid `--chain` values for operations: `polygon` (default/mainnet), `amoy` (Polygon testnet), `mainnet` (Ethereum), `arbitrum`, `optimism`, `base`. ERC-8004 agent operations only support `polygon`. The embedded wallet address is the same on every chain. ```bash -polygon-agent wallet create [--name ] [--chain polygon] [--timeout ] [--print-url] - [--native-limit ] [--usdc-limit ] [--usdt-limit ] - [--token-limit ] # repeatable - [--usdc-to --usdc-amount ] # one-off scoped transfer - [--contract ] # whitelist contract (repeatable) -polygon-agent wallet import --code <6-digit-code> --rid [--name ] -polygon-agent wallet import --ciphertext '|@' [--name ] # legacy -polygon-agent wallet list -polygon-agent wallet address [--name ] -polygon-agent wallet remove [--name ] +agent wallet login [--name ] [--local] [--no-fund] [--force] +# Opens the agentconnect login page; choose Google or email. Works whether the browser is local or remote, so there is no separate headless mode. +# --local falls back to the legacy loopback flow (raw Google URL + localhost callback; browser must be on this machine; Google only). --remote is deprecated (now a no-op with a notice). +agent wallet logout [--name ] # clears the local session +agent wallet list +agent wallet address [--name ] +agent wallet remove [--name ] ``` ### Operations ```bash -polygon-agent balances [--wallet ] [--chain ] [--chains ] -polygon-agent send --to --amount [--symbol ] [--token ] [--decimals ] [--broadcast] -polygon-agent send-native --to --amount [--broadcast] [--direct] -polygon-agent send-token --symbol --to --amount [--token ] [--decimals ] [--broadcast] -polygon-agent swap --from --to --amount [--to-chain ] [--slippage ] [--broadcast] -polygon-agent deposit --asset --amount [--protocol aave|morpho] [--broadcast] -polygon-agent withdraw --position --amount [--chain ] [--broadcast] -polygon-agent fund [--wallet ] [--token ] -polygon-agent x402-pay --url --wallet [--method GET] [--body ] [--header Key:Value] +agent balances [--wallet ] [--chain ] [--chains ] +agent send --to --amount [--symbol ] [--token ] [--decimals ] [--broadcast] +agent send-native --to --amount [--broadcast] [--direct] +agent send-token --symbol --to --amount [--token ] [--decimals ] [--broadcast] +agent swap --from --to --amount [--to-chain ] [--slippage ] [--broadcast] +agent deposit --asset --amount [--protocol aave|morpho] [--broadcast] +agent withdraw --position --amount [--chain ] [--broadcast] +agent fund [--wallet ] [--token ] +agent x402-pay --url --wallet [--method GET] [--body ] [--header Key:Value] ``` ### Agent (ERC-8004) ```bash -polygon-agent agent register --name [--agent-uri ] [--metadata ] [--broadcast] -polygon-agent agent wallet --agent-id -polygon-agent agent metadata --agent-id --key -polygon-agent agent reputation --agent-id [--tag1 ] [--tag2 ] -polygon-agent agent reviews --agent-id [--tag1 ] [--tag2 ] [--revoked] -polygon-agent agent feedback --agent-id --value [--tag1 ] [--tag2 ] [--endpoint ] [--feedback-uri ] [--broadcast] +agent agent register --name [--agent-uri ] [--metadata ] [--broadcast] +agent agent wallet --agent-id +agent agent metadata --agent-id --key +agent agent reputation --agent-id [--tag1 ] [--tag2 ] +agent agent reviews --agent-id [--tag1 ] [--tag2 ] [--revoked] +agent agent feedback --agent-id --value [--tag1 ] [--tag2 ] [--endpoint ] [--feedback-uri ] [--broadcast] ``` **ERC-8004 contracts (Polygon mainnet):** @@ -166,35 +164,18 @@ polygon-agent agent feedback --agent-id --value [--tag1 ] [--tag ## Key Behaviors - **Dry-run by default** — all write commands require `--broadcast` to execute -- **Smart defaults** — `--wallet main`, `--chain polygon`, auto-wait on `wallet create` +- **Smart defaults** — `--wallet main`, `--chain polygon` - **`balances --chains`** — comma-separated chains (max 20); two or more return JSON with `multiChain: true` and a `chains` array (same wallet address on each) -- **Fee preference** — auto-selects USDC over native POL when both available -- **`fund`** — returns `https://wallet.polygon.technology` as the `fundingUrl`. Always run `polygon-agent fund` to get the URL and wallet address — never hardcode or construct manually. -- **`deposit`** — picks highest-TVL pool via Trails `getEarnPools` and deposits directly. Aave V3 Pool (`0x794a61358d6845594f94dc1db02a252b5b4814ad`) is auto-whitelisted in all sessions. Full deposit reference: https://agentconnect.polygon.technology/polygon-defi/SKILL.md -- **Gas reserve** — when using `deposit` or any command that spends tokens, always reserve at least 0.1 USDC or 0.1 POL in the wallet for gas. Never attempt to spend the full balance. The `deposit` command enforces a 0.1 reserve automatically, but the agent must apply the same rule when constructing amounts for `send`, `swap`, or direct contract calls. -- **`withdraw`** — `--position` = aToken or ERC-4626 vault; `--amount` = `max` or underlying units (Aave / vault). Dry-run JSON includes `poolAddress` / `vault`. Broadcast needs session on the **same chain** as `--chain`, with pool/vault + underlying token whitelisted where the relayer touches them -- **`x402-pay`** — probes endpoint for 402, smart wallet funds builder EOA with exact token amount, EOA signs EIP-3009 payment. Chain auto-detected from 402 response +- **Fee preference** — auto-selects USDC over native POL when both available; the relayer pays gas in whichever fee token the wallet can afford +- **`fund`** — returns the agentconnect dashboard funding URL (wallet and chain prefilled) as the `fundingUrl`. Always run `agent fund` to get the URL and wallet address — never hardcode or construct manually. +- **`deposit`** — picks highest-TVL pool via Trails `getEarnPools` and deposits directly. Full deposit reference: https://agentconnect.polygon.technology/polygon-defi/SKILL.md +- **Gas reserve** — when using `deposit` or any command that spends tokens, always reserve at least 0.1 USDC or 0.1 POL in the wallet for gas. Never attempt to spend the full balance. The `deposit` command enforces a 0.1 reserve automatically, but the agent must apply the same rule when constructing amounts for `send`, `swap`, or `call`. +- **`withdraw`** — `--position` = aToken or ERC-4626 vault; `--amount` = `max` or underlying units (Aave / vault). Dry-run JSON includes `poolAddress` / `vault`. +- **`x402-pay`** — probes endpoint for 402, the wallet funds a builder EOA with the exact token amount, the EOA signs the EIP-3009 payment. Chain auto-detected from the 402 response +- **`call`** — submit arbitrary pre-encoded calldata: `agent call --to --data 0x... [--value ] [--prefer-native-fee] [--broadcast]`. The wallet can call any contract (no permission scoping in the V3 model) - **`send-native --direct`** — bypasses ValueForwarder contract for direct EOA transfer -- **Session permissions** — without `--usdc-limit` etc., session gets bare-bones defaults and may not transact -- **Session expiry** — 6 months from creation -- **One-pass session setup** — if the user's intent involves DeFi (deposit, yield, swap, Aave, Morpho), include any additional contracts (Morpho vaults etc.) in the initial `wallet create` call. Never create a bare session and then ask the user to re-approve when a deposit is later attempted. - -## Wallet Creation Flow (v2 Relay) - -`wallet create` uses a Cloudflare Durable Object relay and a 6-digit out-of-band code — no cloudflared tunnel required. The browser encrypts the approved session with an X25519 key negotiated via the relay; the 6-digit code is the decryption key entered in the terminal. - -**`--print-url` flag:** Use this in headless or non-interactive environments (CI, remote shells) where `wallet create` can't block waiting for the code. The CLI prints the approval URL and exits immediately. Complete the flow separately: -```bash -polygon-agent wallet import --code <6-digit-code> --rid -``` - -## CRITICAL: Wallet Approval URL - -When `wallet create` outputs a URL in the `url` or `approvalUrl` field, send the **complete, untruncated URL** to the user. The URL contains the relay request ID required for session approval. - -- Do NOT shorten, summarize, or add `...` to the URL -- Do NOT split the URL across multiple messages -- Output the raw URL exactly as returned by the CLI +- **No permission scoping** — the V3 embedded wallet can call any contract and spend any amount it holds; there are no per-contract whitelists or spend limits. Guard spending in agent logic, not at the wallet layer. +- **Session expiry** — ~1 week from login; on expiry, re-run `wallet login` ## Presenting Results to the User @@ -208,7 +189,7 @@ CLI commands output JSON (non-TTY). After running a command, always render the r | `deposit` | Summary: amount, asset, protocol, pool address. If broadcast, show tx hash + explorer link. | | `withdraw` | Summary: `kind` (aave / erc4626), position, amount, pool or vault. If broadcast, show tx hash + explorer link. | | `fund` | Show the `fundingUrl` as a clickable link with a brief instruction to open it. | -| `wallet create` / `wallet list` | Wallet name, truncated address, chain in a small table or bullet list. | +| `wallet login` / `wallet list` | Wallet name, truncated address, chain in a small table or bullet list. | | `agent register` | Show agent name and tx hash as a code span with Polygonscan link. Remind user to retrieve `agentId` from the Registered event on the Logs tab. | | `agent wallet` | Show `agentId`, wallet address, and whether a wallet is set. | | `agent metadata` | Show `agentId`, key, and decoded value. | @@ -224,18 +205,10 @@ CLI commands output JSON (non-TTY). After running a command, always render the r | Issue | Fix | |-------|-----| -| `Builder configured already` | Add `--force` | -| `Missing SEQUENCE_PROJECT_ACCESS_KEY` | Run `setup` first | -| `Missing wallet` | `wallet list`, re-run `wallet create` | -| `Session expired` | Re-run `wallet create` (6-month expiry) | -| `Fee option errors` | Set `POLYGON_AGENT_DEBUG_FEE=1`, ensure wallet has funds | -| `Timed out waiting for wallet approval` | Add `--timeout 600` | -| `Invalid code: hash mismatch` | Wrong 6-digit code entered — retry (3 attempts allowed) | -| `Relay request not found` | Session expired or already used — re-run `wallet create` (or `wallet create --print-url`) | -| Deposit session rejected | Re-create wallet with `--contract --contract ` (both required: token approve + pool call) | -| `withdraw` / broadcast: wrong chain or session rejects | Use `wallet create --chain ` and `--contract` for pool/vault + underlying ERC-20 on that chain; omit tight `--usdc-limit` if it blocks fee transfers | -| `Stored explicit session is missing pk` | Re-link: `wallet import --code …` after `wallet create` | -| Wrong recipient in Trails widget | Run `polygon-agent fund` (do not construct the URL manually) | +| `Wallet not found` | `wallet list`, then `agent wallet login` | +| Session expired (`OMS_SESSION_EXPIRED`) | Run `agent wallet login` (~1-week lifetime) | +| `Fee option errors` | Set `POLYGON_AGENT_DEBUG_FEE=1`, ensure wallet has POL or a fee token. For native-only wallets, add `--prefer-native-fee` on `call` | +| Wrong recipient in Trails widget | Run `agent fund` (do not construct the URL manually) | | `x402-pay`: no 402 response | Endpoint doesn't require x402 payment, or URL is wrong | | `x402-pay`: payment token mismatch | Chain/token in the 402 response differs from wallet — check `--wallet` points to the right chain | | `x402-pay`: EOA funding failed | Wallet lacks sufficient balance to cover the payment amount — run `balances` and fund if needed | @@ -243,8 +216,8 @@ CLI commands output JSON (non-TTY). After running a command, always render the r ## File Structure ``` ~/.polygon-agent/ -├── .encryption-key # AES-256-GCM key (auto-generated, 0600) -├── builder.json # EOA privateKey (encrypted), eoaAddress, accessKey, projectId -├── wallets/.json # walletAddress, session, chainId, chain -└── requests/.json # Pending wallet creation requests (deleted after successful import) +├── .encryption-key # AES-256-GCM key (auto-generated, 0600) +├── builder.json # publishableKey, omsProjectId, polymarket/EOA keys (encrypted) +├── wallets/.json # OMS wallet pointer: walletAddress, loginMethod +└── oms// # OMS SDK session storage + encrypted credential key ``` diff --git a/skills/polygon-agent-cli/SKILL.md b/skills/polygon-agent-cli/SKILL.md index 091e05f..9a50fd1 100644 --- a/skills/polygon-agent-cli/SKILL.md +++ b/skills/polygon-agent-cli/SKILL.md @@ -1,53 +1,61 @@ --- name: polygon-agent-cli -description: "Complete Polygon agent toolkit for on-chain operations on Polygon. Use this skill whenever helping an agent set up a wallet, check balances, send or swap tokens, bridge assets, deposit or withdraw from yield (Aave aTokens, ERC-4626 vaults), register on-chain identity, submit or query reputation/feedback, or make x402 micropayments. Covers the full lifecycle: Sequence smart contract wallets, Trails DeFi actions, ERC-8004 identity + reputation, x402 payments. Single CLI entry point (`polygon-agent`), AES-256-GCM encrypted storage." +description: "Complete Polygon agent toolkit for on-chain operations on Polygon. Use this skill whenever helping an agent set up a wallet, check balances, send or swap tokens, bridge assets, deposit or withdraw from yield (Aave aTokens, ERC-4626 vaults), register on-chain identity, submit or query reputation/feedback, or make x402 micropayments. Covers the full lifecycle: OMS smart contract wallets, Trails DeFi actions, ERC-8004 identity + reputation, x402 payments. Single CLI entry point (`agent`), AES-256-GCM encrypted storage." --- # Polygon Agentic CLI ## Prerequisites -- Node.js 20+ +- Node.js 22+ - Install globally: `npm install -g @polygonlabs/agent-cli` (reinstall to update) -- Entry point: `polygon-agent ` +- Entry point: `agent ` - Storage: `~/.polygon-agent/` (AES-256-GCM encrypted) -> **Note for the agent: on first install, tell the user this is a global npm install** — installs the `polygon-agent` CLI system-wide so it runs from any terminal, may need sudo on some setups, re-running the same command updates it, and `npm uninstall -g @polygonlabs/agent-cli` removes it. Mention once on first install. +> **Note for the agent: on first install, tell the user this is a global npm install** — installs the `agent` CLI system-wide so it runs from any terminal, may need sudo on some setups, re-running the same command updates it, and `npm uninstall -g @polygonlabs/agent-cli` removes it. Mention once on first install. ## If a command fails with "Unknown argument" or "command not found" This skill is versioned with the CLI — commands and flags drift across releases. Check your version, compare to latest, and upgrade if behind: ```bash -polygon-agent --version # currently installed +agent --version # currently installed npm view @polygonlabs/agent-cli version # latest published npm install -g @polygonlabs/agent-cli@latest # upgrade ``` ## Architecture +The CLI uses the **OMS (Open Money Stack) V3 embedded-wallet** model (`@polygonlabs/oms-wallet`). By default, `wallet login` opens the agentconnect login page (`POLYGON_AGENT_LOGIN_UI`, default `https://agentconnect.polygon.technology`), where the user chooses Google or email (email sends a 6-digit code to the user's inbox, entered on the page). This works whether the browser is on this machine or a different one, so there is no separate headless mode. `--local` falls back to the legacy loopback flow (raw Google sign-in URL plus a localhost callback; browser must be on this same machine; Google only). `--remote` is deprecated and is now a no-op that prints a notice. Once the user signs in, the wallet is created or unlocked and the session credential is stored encrypted on disk. There is no on-chain permission scoping. + | Wallet | Created by | Purpose | Fund? | |--------|-----------|---------|-------| -| EOA | `setup` | Auth with Sequence Builder | NO | -| Ecosystem Wallet | `wallet create` | Primary spending wallet | YES | +| Embedded wallet (V3) | `wallet login` | Primary spending wallet | YES | + +The wallet address is the **same across all EVM chains**. Sessions last ~1 week before re-login is needed. ## Environment Variables -### Access key — one key, many names +### OMS credentials (optional) -`SEQUENCE_PROJECT_ACCESS_KEY`, `SEQUENCE_INDEXER_ACCESS_KEY`, and `TRAILS_API_KEY` are **all the same key** — the Sequence project access key created during `setup`. The CLI treats them as aliases and falls back through all of them automatically. +No setup step is required. The CLI ships a default OMS publishable key, and `wallet login` automatically provisions a dedicated Builder project and access key on first login, saving it to `~/.polygon-agent/builder.json`. -After `setup` runs the key is stored in `~/.polygon-agent/builder.json`. Every CLI invocation bootstraps it into the environment — no `export` is needed. In a fresh agent session with no environment variables set, simply run commands and the CLI reads credentials from disk. +| Variable | Description | +|----------|-------------| +| `OMS_PUBLISHABLE_KEY` | Advanced override: point at your own OMS Builder project instead of the default | -Only set these manually to override the stored value (e.g. to point at a different project): +Set it via env, or persist once with `setup` so every command reads it from `~/.polygon-agent/builder.json`: ```bash -export SEQUENCE_PROJECT_ACCESS_KEY= # also covers TRAILS_API_KEY and indexer calls +agent setup --oms-publishable-key ``` +`--oms-project-id ` is also accepted but optional — it's kept only as legacy display metadata. Plain `setup` (no key) still works for manual or `--force` re-provisioning. + ### Optional overrides | Variable | Default | |----------|---------| -| `SEQUENCE_ECOSYSTEM_CONNECTOR_URL` | `https://agentconnect.polygon.technology` | -| `SEQUENCE_DAPP_ORIGIN` | Same as connector URL origin | +| `POLYGON_AGENT_LOGIN_UI` | Base URL of the browser login page opened by `wallet login` (default `https://agentconnect.polygon.technology`) | +| `POLYGON_AGENT_OIDC_RELAY` | Base URL of the OIDC relay used by `wallet login` (default `https://oidc-relay.polygon.technology`); also settable per run with `--relay-url` | +| `SEQUENCE_PROJECT_ACCESS_KEY` | Used only as the Trails API key for DeFi earn-pool lookups (optional) | | `TRAILS_TOKEN_MAP_JSON` | Token-directory lookup | | `POLYGON_AGENT_DEBUG_FETCH` | Off — logs HTTP to `~/.polygon-agent/fetch-debug.log` | | `POLYGON_AGENT_DEBUG_FEE` | Off — dumps fee options to stderr | @@ -55,38 +63,30 @@ export SEQUENCE_PROJECT_ACCESS_KEY= # also covers TRAILS_API_KEY and index ## Complete Setup Flow ```bash -# Step 1: Setup (creates EOA + Sequence project, stores access key to disk) -polygon-agent setup --name "MyAgent" -# → saves privateKey (not shown again), eoaAddress, accessKey to ~/.polygon-agent/builder.json -# → all subsequent commands auto-load the access key from disk — no export needed - -# Step 2: Create ecosystem wallet (opens browser, waits for 6-digit code) -# Aave V3 Pool is auto-whitelisted in all sessions. For Morpho or other DeFi vaults, -# add --contract flags as needed. -polygon-agent wallet create --usdc-limit 50 --native-limit 5 \ - --contract 0xc2132D05D31c914a87C6611C10748AEb04B58e8F \ - --contract 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619 \ - --contract 0x781fb7f6d845e3be129289833b04d43aa8558c42 \ - --contract 0xf5c81d25ee174d83f1fd202ca94ae6070d073ccf \ - --contract 0x3f33f9f7e2d7cfbcbdf8ea8b870a6e3d449664c2 -# → opens https://agentconnect.polygon.technology/link?rid=&... -# → user approves in browser, browser shows a 6-digit code -# → enter the 6-digit code in the terminal when prompted -# → session saved to ~/.polygon-agent/wallets/main.json -# → notify the user and send them to https://agentconnect.polygon.technology/?rid= -# so they can fund their wallet with access to the session - -# Step 3: Fund wallet -polygon-agent fund +# Step 1: Log in in the browser +agent wallet login +# → opens the agentconnect login page; choose Google or email (email sends +# a 6-digit code to the user's inbox, entered on the page) +# → works whether the browser is on this machine or elsewhere, so there is +# no separate headless mode +# → --local falls back to the legacy loopback flow (Google only, browser +# must be on this machine) +# → session saved to ~/.polygon-agent/oms/main/; prints the walletAddress +# → no setup step needed: the CLI ships a default OMS publishable key, and +# login auto-provisions a Builder project + access key to +# ~/.polygon-agent/builder.json + +# Step 2: Fund wallet +agent fund # → reads walletAddress from session, builds Trails widget URL with toAddress= # → ALWAYS run this command to get the URL — never construct it manually or hardcode any address # → send the returned `fundingUrl` to the user; `walletAddress` in the output confirms the recipient -# Step 4: Verify balances -polygon-agent balances +# Step 3: Verify balances +agent balances -# Step 5: Register agent on-chain (ERC-8004, Polygon mainnet only) -polygon-agent agent register --name "MyAgent" --broadcast +# Step 4: Register agent on-chain (ERC-8004, Polygon mainnet only) +agent agent register --name "MyAgent" --broadcast # → mints ERC-721 NFT, emits Registered event containing agentId # → retrieve agentId: open the tx on https://polygonscan.com, go to Logs tab, # find the Registered event — agentId is the first indexed parameter @@ -103,11 +103,11 @@ For specific workflows, fetch and load the relevant sub-skill **before attemptin | DeFi — swap, deposit, withdraw, yield | https://agentconnect.polygon.technology/polygon-defi/SKILL.md | | x402 discovery & pay-per-call APIs | https://agentconnect.polygon.technology/polygon-discovery/SKILL.md | -> **IMPORTANT — x402 calls:** If the user asks to use x402 to fetch data (Twitter/X profiles, web search, news, AI images, code review, etc.), follow these steps in order before making any request: +> **IMPORTANT — x402 calls:** If the user asks to use x402 to fetch data or call a service (web search, scraping, news, LLM inference, email, on-chain wallet analytics, multi-chain RPC, etc.), follow these steps in order before making any request: > > 1. Fetch and read the discovery skill: `GET https://agentconnect.polygon.technology/polygon-discovery/SKILL.md` -> 2. Run `polygon-agent wallet list` — if no wallet exists, run through the wallet creation flow: `polygon-agent setup` (if not already done), then `polygon-agent wallet create` to open a browser session and establish a secure encrypted wallet session. Enter the 6-digit code when prompted, then fund the wallet before continuing. -> 3. Run `polygon-agent balances` — confirm USDC is available before proceeding; x402 calls will fail with an EOA funding error if the wallet is empty +> 2. Run `agent wallet list` — if no wallet exists, log in: `agent wallet login` and sign in on the login page (Google or email), then fund the wallet before continuing. No setup step is needed first. +> 3. Run `agent balances` — confirm USDC is available before proceeding; x402 calls will fail with an EOA funding error if the wallet is empty > > Do not guess endpoints or search the web for x402 providers. The discovery skill documents the correct, working endpoints with exact URL formats. @@ -117,46 +117,44 @@ For specific workflows, fetch and load the relevant sub-skill **before attemptin ### Setup ```bash -polygon-agent setup --name [--force] +agent setup [--name ] [--force] + [--oms-publishable-key ] [--oms-project-id ] # save OMS credentials (project id optional/legacy) ``` ### Wallet -Valid `--chain` values: `polygon` (default/mainnet), `amoy` (Polygon testnet), `mainnet` (Ethereum), `arbitrum`, `optimism`, `base`. ERC-8004 agent operations only support `polygon`. +Valid `--chain` values for operations: `polygon` (default/mainnet), `amoy` (Polygon testnet), `mainnet` (Ethereum), `arbitrum`, `optimism`, `base`. ERC-8004 agent operations only support `polygon`. The embedded wallet address is the same on every chain. ```bash -polygon-agent wallet create [--name ] [--chain polygon] [--timeout ] [--print-url] - [--native-limit ] [--usdc-limit ] [--usdt-limit ] - [--token-limit ] # repeatable - [--usdc-to --usdc-amount ] # one-off scoped transfer - [--contract ] # whitelist contract (repeatable) -polygon-agent wallet import --code <6-digit-code> --rid [--name ] -polygon-agent wallet import --ciphertext '|@' [--name ] # legacy -polygon-agent wallet list -polygon-agent wallet address [--name ] -polygon-agent wallet remove [--name ] +agent wallet login [--name ] [--local] [--no-fund] [--force] +# Opens the agentconnect login page; choose Google or email. Works whether the browser is local or remote, so there is no separate headless mode. +# --local falls back to the legacy loopback flow (raw Google URL + localhost callback; browser must be on this machine; Google only). --remote is deprecated (now a no-op with a notice). +agent wallet logout [--name ] # clears the local session +agent wallet list +agent wallet address [--name ] +agent wallet remove [--name ] ``` ### Operations ```bash -polygon-agent balances [--wallet ] [--chain ] [--chains ] -polygon-agent send --to --amount [--symbol ] [--token ] [--decimals ] [--broadcast] -polygon-agent send-native --to --amount [--broadcast] [--direct] -polygon-agent send-token --symbol --to --amount [--token ] [--decimals ] [--broadcast] -polygon-agent swap --from --to --amount [--to-chain ] [--slippage ] [--broadcast] -polygon-agent deposit --asset --amount [--protocol aave|morpho] [--broadcast] -polygon-agent withdraw --position --amount [--chain ] [--broadcast] -polygon-agent fund [--wallet ] [--token ] -polygon-agent x402-pay --url --wallet [--method GET] [--body ] [--header Key:Value] +agent balances [--wallet ] [--chain ] [--chains ] +agent send --to --amount [--symbol ] [--token ] [--decimals ] [--broadcast] +agent send-native --to --amount [--broadcast] [--direct] +agent send-token --symbol --to --amount [--token ] [--decimals ] [--broadcast] +agent swap --from --to --amount [--to-chain ] [--slippage ] [--broadcast] +agent deposit --asset --amount [--protocol aave|morpho] [--broadcast] +agent withdraw --position --amount [--chain ] [--broadcast] +agent fund [--wallet ] [--token ] +agent x402-pay --url --wallet [--method GET] [--body ] [--header Key:Value] ``` ### Agent (ERC-8004) ```bash -polygon-agent agent register --name [--agent-uri ] [--metadata ] [--broadcast] -polygon-agent agent wallet --agent-id -polygon-agent agent metadata --agent-id --key -polygon-agent agent reputation --agent-id [--tag1 ] [--tag2 ] -polygon-agent agent reviews --agent-id [--tag1 ] [--tag2 ] [--revoked] -polygon-agent agent feedback --agent-id --value [--tag1 ] [--tag2 ] [--endpoint ] [--feedback-uri ] [--broadcast] +agent agent register --name [--agent-uri ] [--metadata ] [--broadcast] +agent agent wallet --agent-id +agent agent metadata --agent-id --key +agent agent reputation --agent-id [--tag1 ] [--tag2 ] +agent agent reviews --agent-id [--tag1 ] [--tag2 ] [--revoked] +agent agent feedback --agent-id --value [--tag1 ] [--tag2 ] [--endpoint ] [--feedback-uri ] [--broadcast] ``` **ERC-8004 contracts (Polygon mainnet):** @@ -166,35 +164,17 @@ polygon-agent agent feedback --agent-id --value [--tag1 ] [--tag ## Key Behaviors - **Dry-run by default** — all write commands require `--broadcast` to execute -- **Smart defaults** — `--wallet main`, `--chain polygon`, auto-wait on `wallet create` +- **Smart defaults** — `--wallet main`, `--chain polygon` - **`balances --chains`** — comma-separated chains (max 20); two or more return JSON with `multiChain: true` and a `chains` array (same wallet address on each) -- **Fee preference** — auto-selects USDC over native POL when both available -- **`fund`** — returns `https://wallet.polygon.technology` as the `fundingUrl`. Always run `polygon-agent fund` to get the URL and wallet address — never hardcode or construct manually. -- **`deposit`** — picks highest-TVL pool via Trails `getEarnPools` and deposits directly. Aave V3 Pool (`0x794a61358d6845594f94dc1db02a252b5b4814ad`) is auto-whitelisted in all sessions. Full deposit reference: https://agentconnect.polygon.technology/polygon-defi/SKILL.md +- **Fee preference** — auto-selects USDC over native POL when both available; the relayer pays gas in whichever fee token the wallet can afford +- **`fund`** — returns the agentconnect dashboard funding URL (wallet and chain prefilled) as the `fundingUrl`. Always run `agent fund` to get the URL and wallet address — never hardcode or construct manually. +- **`deposit`** — picks highest-TVL pool via Trails `getEarnPools` and deposits directly. Full deposit reference: https://agentconnect.polygon.technology/polygon-defi/SKILL.md - **Gas reserve** — when using `deposit` or any command that spends tokens, always reserve at least 0.1 USDC or 0.1 POL in the wallet for gas. Never attempt to spend the full balance. The `deposit` command enforces a 0.1 reserve automatically, but the agent must apply the same rule when constructing amounts for `send`, `swap`, or direct contract calls. -- **`withdraw`** — `--position` = aToken or ERC-4626 vault; `--amount` = `max` or underlying units (Aave / vault). Dry-run JSON includes `poolAddress` / `vault`. Broadcast needs session on the **same chain** as `--chain`, with pool/vault + underlying token whitelisted where the relayer touches them +- **`withdraw`** — `--position` = aToken or ERC-4626 vault; `--amount` = `max` or underlying units (Aave / vault). Dry-run JSON includes `poolAddress` / `vault`. - **`x402-pay`** — probes endpoint for 402, smart wallet funds builder EOA with exact token amount, EOA signs EIP-3009 payment. Chain auto-detected from 402 response - **`send-native --direct`** — bypasses ValueForwarder contract for direct EOA transfer -- **Session permissions** — without `--usdc-limit` etc., session gets bare-bones defaults and may not transact -- **Session expiry** — 6 months from creation -- **One-pass session setup** — if the user's intent involves DeFi (deposit, yield, swap, Aave, Morpho), include any additional contracts (Morpho vaults etc.) in the initial `wallet create` call. Never create a bare session and then ask the user to re-approve when a deposit is later attempted. - -## Wallet Creation Flow (v2 Relay) - -`wallet create` uses a Cloudflare Durable Object relay and a 6-digit out-of-band code — no cloudflared tunnel required. The browser encrypts the approved session with an X25519 key negotiated via the relay; the 6-digit code is the decryption key entered in the terminal. - -**`--print-url` flag:** Use this in headless or non-interactive environments (CI, remote shells) where `wallet create` can't block waiting for the code. The CLI prints the approval URL and exits immediately. Complete the flow separately: -```bash -polygon-agent wallet import --code <6-digit-code> --rid -``` - -## CRITICAL: Wallet Approval URL - -When `wallet create` outputs a URL in the `url` or `approvalUrl` field, send the **complete, untruncated URL** to the user. The URL contains the relay request ID required for session approval. - -- Do NOT shorten, summarize, or add `...` to the URL -- Do NOT split the URL across multiple messages -- Output the raw URL exactly as returned by the CLI +- **No permission scoping** — the V3 embedded wallet can call any contract and spend any amount it holds; there are no per-contract whitelists or spend limits. Guard spending in agent logic, not at the wallet layer. +- **Session expiry** — ~1 week from login; on expiry, re-run `wallet login` ## Presenting Results to the User @@ -208,7 +188,7 @@ CLI commands output JSON (non-TTY). After running a command, always render the r | `deposit` | Summary: amount, asset, protocol, pool address. If broadcast, show tx hash + explorer link. | | `withdraw` | Summary: `kind` (aave / erc4626), position, amount, pool or vault. If broadcast, show tx hash + explorer link. | | `fund` | Show the `fundingUrl` as a clickable link with a brief instruction to open it. | -| `wallet create` / `wallet list` | Wallet name, truncated address, chain in a small table or bullet list. | +| `wallet login` / `wallet list` | Wallet name, truncated address, chain in a small table or bullet list. | | `agent register` | Show agent name and tx hash as a code span with Polygonscan link. Remind user to retrieve `agentId` from the Registered event on the Logs tab. | | `agent wallet` | Show `agentId`, wallet address, and whether a wallet is set. | | `agent metadata` | Show `agentId`, key, and decoded value. | @@ -224,18 +204,10 @@ CLI commands output JSON (non-TTY). After running a command, always render the r | Issue | Fix | |-------|-----| -| `Builder configured already` | Add `--force` | -| `Missing SEQUENCE_PROJECT_ACCESS_KEY` | Run `setup` first | -| `Missing wallet` | `wallet list`, re-run `wallet create` | -| `Session expired` | Re-run `wallet create` (6-month expiry) | -| `Fee option errors` | Set `POLYGON_AGENT_DEBUG_FEE=1`, ensure wallet has funds | -| `Timed out waiting for wallet approval` | Add `--timeout 600` | -| `Invalid code: hash mismatch` | Wrong 6-digit code entered — retry (3 attempts allowed) | -| `Relay request not found` | Session expired or already used — re-run `wallet create` (or `wallet create --print-url`) | -| Deposit session rejected | Re-create wallet with `--contract --contract ` (both required: token approve + pool call) | -| `withdraw` / broadcast: wrong chain or session rejects | Use `wallet create --chain ` and `--contract` for pool/vault + underlying ERC-20 on that chain; omit tight `--usdc-limit` if it blocks fee transfers | -| `Stored explicit session is missing pk` | Re-link: `wallet import --code …` after `wallet create` | -| Wrong recipient in Trails widget | Run `polygon-agent fund` (do not construct the URL manually) | +| `Wallet not found` | `wallet list`, then `agent wallet login` | +| Session expired (`OMS_SESSION_EXPIRED`) | Run `agent wallet login` (~1-week lifetime) | +| `Fee option errors` | Set `POLYGON_AGENT_DEBUG_FEE=1`, ensure wallet has POL or a fee token. For native-only wallets, add `--prefer-native-fee` on `call` | +| Wrong recipient in Trails widget | Run `agent fund` (do not construct the URL manually) | | `x402-pay`: no 402 response | Endpoint doesn't require x402 payment, or URL is wrong | | `x402-pay`: payment token mismatch | Chain/token in the 402 response differs from wallet — check `--wallet` points to the right chain | | `x402-pay`: EOA funding failed | Wallet lacks sufficient balance to cover the payment amount — run `balances` and fund if needed | @@ -244,7 +216,7 @@ CLI commands output JSON (non-TTY). After running a command, always render the r ``` ~/.polygon-agent/ ├── .encryption-key # AES-256-GCM key (auto-generated, 0600) -├── builder.json # EOA privateKey (encrypted), eoaAddress, accessKey, projectId -├── wallets/.json # walletAddress, session, chainId, chain -└── requests/.json # Pending wallet creation requests (deleted after successful import) +├── builder.json # publishableKey, omsProjectId (encrypted) +├── wallets/.json # OMS wallet pointer: walletAddress, loginMethod +└── oms// # OMS SDK session storage + encrypted credential key ``` diff --git a/skills/polygon-defi/SKILL.md b/skills/polygon-defi/SKILL.md index 56aa7f2..f8789d2 100644 --- a/skills/polygon-defi/SKILL.md +++ b/skills/polygon-defi/SKILL.md @@ -7,25 +7,13 @@ description: DeFi operations on Polygon using the Polygon Agent CLI. Covers same ## Session Prerequisites -**Before any DeFi operation, the wallet session must include the token contracts and pool contracts.** If the user does not yet have a session, or has an older session that predates this list, create one now — do not wait until a deposit fails: +**Before any DeFi operation, the wallet must be logged in.** The embedded wallet can call any contract and spend any amount it holds — there is no contract whitelist and no per-token spend limit, so no special setup is needed for deposits, swaps, or withdrawals. If the user is not logged in, log in now: ```bash -polygon-agent wallet create --usdc-limit 50 \ - --contract 0xc2132D05D31c914a87C6611C10748AEb04B58e8F \ - --contract 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619 \ - --contract 0x781fb7f6d845e3be129289833b04d43aa8558c42 \ - --contract 0xf5c81d25ee174d83f1fd202ca94ae6070d073ccf \ - --contract 0x3f33f9f7e2d7cfbcbdf8ea8b870a6e3d449664c2 +agent wallet login ``` -**Aave V3 Pool (`0x794a61358d6845594f94dc1db02a252b5b4814ad`) is auto-whitelisted in every session** — no `--contract` flag needed for it. The above command adds: -- USDT: `0xc2132D05D31c914a87C6611C10748AEb04B58e8F` -- WETH: `0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619` -- Morpho Compound USDC: `0x781fb7f6d845e3be129289833b04d43aa8558c42` -- Morpho Compound WETH: `0xf5c81d25ee174d83f1fd202ca94ae6070d073ccf` -- Morpho Compound POL: `0x3f33f9f7e2d7cfbcbdf8ea8b870a6e3d449664c2` - -If the user already has a session but deposit/swap calls are rejected with a permission error, re-create the session with the above command to pick up all current contracts. +This opens the agentconnect login page in the browser; choose Google or email, and once you sign in the embedded wallet is created or unlocked. This works whether the browser is local or remote, so no extra flags are needed on headless hosts. The wallet address is the same across all chains. Sessions last about a week; if calls start failing with an expired-session error, just re-run `wallet login`. --- @@ -33,25 +21,25 @@ If the user already has a session but deposit/swap calls are rejected with a per ```bash # Dry-run — shows route and output amount -polygon-agent swap --from USDC --to USDT --amount 5 +agent swap --from USDC --to USDT --amount 5 # Execute -polygon-agent swap --from USDC --to USDT --amount 5 --broadcast +agent swap --from USDC --to USDT --amount 5 --broadcast # Custom slippage (default 0.5%) -polygon-agent swap --from USDC --to USDT --amount 5 --slippage 0.005 --broadcast +agent swap --from USDC --to USDT --amount 5 --slippage 0.005 --broadcast ``` ## Bridge Tokens (Cross-Chain) ```bash # Bridge USDC from Polygon to Arbitrum -polygon-agent swap --from USDC --to USDC --amount 0.5 --to-chain arbitrum --broadcast +agent swap --from USDC --to USDC --amount 0.5 --to-chain arbitrum --broadcast # Bridge to other supported chains -polygon-agent swap --from USDC --to USDC --amount 1 --to-chain optimism --broadcast -polygon-agent swap --from USDC --to USDC --amount 1 --to-chain base --broadcast -polygon-agent swap --from USDC --to USDC --amount 1 --to-chain mainnet --broadcast +agent swap --from USDC --to USDC --amount 1 --to-chain optimism --broadcast +agent swap --from USDC --to USDC --amount 1 --to-chain base --broadcast +agent swap --from USDC --to USDC --amount 1 --to-chain mainnet --broadcast ``` Valid `--to-chain` values: `polygon`, `amoy`, `mainnet`, `arbitrum`, `optimism`, `base`. @@ -66,6 +54,7 @@ Use `getEarnPools` to discover live yield opportunities across protocols before curl --request POST \ --url https://trails-api.sequence.app/rpc/Trails/GetEarnPools \ --header 'Content-Type: application/json' \ + --header "X-Access-Key: $TRAILS_API_KEY" \ --data '{"chainIds": [137]}' ``` @@ -78,14 +67,21 @@ All request fields are optional — omit any you don't need to filter on. | `minTvl` | `number` | Minimum TVL in USD | | `maxApy` | `number` | Maximum APY (useful to exclude outlier/at-risk pools) | -### Fetch (agent code) +### API key + +Trails officially requires an API key on every request, passed as an `X-Access-Key` header (get one at https://dashboard.trails.build; rate limits are per key: 50 requests/s, burst 100, 20 QuoteIntent/min). `GetEarnPools` currently answers without a key, but do not rely on that. + +You normally do not need to set anything: the CLI resolves the key automatically as `TRAILS_API_KEY`, else the Sequence access key stored by `agent setup` (in `builder.json`), which Trails accepts. Set `TRAILS_API_KEY` only to use a dedicated Trails key. -The API key is the project access key already available to the agent (`SEQUENCE_PROJECT_ACCESS_KEY`). +### Fetch (agent code) ```typescript const res = await fetch('https://trails-api.sequence.app/rpc/Trails/GetEarnPools', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + 'X-Access-Key': process.env.TRAILS_API_KEY ?? '' + }, body: JSON.stringify({ chainIds: [137] }), }); const { pools } = await res.json(); @@ -126,39 +122,40 @@ interface PoolTokenInfo { > **Tip:** `wrappedTokenGatewayAddress` is set on Aave markets that accept a wrapped native token (WPOL, WETH). Pass this address instead of `depositAddress` when depositing POL/ETH directly. ---- +### Current Trails earn surface (Yield API) -## Deposit to Earn Yield +`GetEarnPools` is the endpoint the CLI's `deposit` command uses today and it remains live, but Trails' current generation earn surface is the **Yield API** at the same base URL: `YieldGetMarkets`, `YieldGetProviders`, `YieldCreateEnterAction`, `YieldCreateExitAction`, and `YieldGetAggregateBalances` (docs: https://docs.trails.build). Query `YieldGetMarkets` when you need markets beyond the Aave and Morpho pools that `GetEarnPools` returns: -Pool discovery uses `TrailsApi.getEarnPools` — picks the most liquid pool (highest TVL) for the asset on the requested chain. No hardcoded addresses — the pool is resolved at runtime. Supported chains: Polygon, Base, Arbitrum, Optimism, Ethereum mainnet (any chain Trails indexes). +```bash +curl --request POST \ + --url https://trails-api.sequence.app/rpc/Trails/YieldGetMarkets \ + --header 'Content-Type: application/json' \ + --header "X-Access-Key: $TRAILS_API_KEY" \ + --data '{}' +``` -**Gas requirement:** The wallet needs POL for gas, or a session created with `--usdc-limit` to enable USDC paymaster. If the wallet has no POL, create the session with `--usdc-limit 50`. The CLI always reserves 0.1 USDC for gas — never deposit the full balance. If the requested amount would leave less than 0.1 USDC, the CLI auto-reduces the deposit and prints a note. +The response is `{ items: [...] }` with per-market `inputTokens`, provider, and network fields. Note that Trails' intent protocol is now v1.5 (HydrateProxy executor); the API still serves the v1 flow that `agent swap` uses, so existing commands are unaffected. -**Session setup:** The wallet session must whitelist the token contract and the pool deposit contract, or the relay will reject the transaction with a 400 error. Run a dry-run first to get the exact addresses, then create (or re-create) the session with both contracts: +--- -```bash -# 1. Dry-run to discover the token address and pool depositAddress -polygon-agent deposit --asset USDC --amount 1 +## Deposit to Earn Yield -# 2. Create session with those contracts whitelisted (prevents 400 permission error on broadcast) -polygon-agent wallet create --usdc-limit 50 --contract --contract +Pool discovery uses `TrailsApi.getEarnPools` — picks the most liquid pool (highest TVL) for the asset on the requested chain. No hardcoded addresses — the pool is resolved at runtime. Supported chains: Polygon, Base, Arbitrum, Optimism, Ethereum mainnet (any chain Trails indexes). -# 3. Broadcast -polygon-agent deposit --asset USDC --amount 1 --broadcast -``` +**Gas requirement:** The relayer pays gas in USDC or POL, whichever the wallet can afford — so the only requirement is that the wallet holds the funds being deposited plus a little POL or USDC for gas. The CLI always reserves 0.1 USDC for gas — never deposit the full balance. If the requested amount would leave less than 0.1 USDC, the CLI auto-reduces the deposit and prints a note. -Omitting `--contract` for the deposit pool is the most common cause of a "Request aborted" (code 1005) error on broadcast. +The embedded wallet can call any contract, so deposits work without pre-authorizing the token or pool contract — just dry-run, then broadcast: ```bash # Dry-run — shows pool name, APY, TVL, and deposit address before committing -polygon-agent deposit --asset USDC --amount 0.3 +agent deposit --asset USDC --amount 0.3 # Execute — deposits into the highest-TVL active pool -polygon-agent deposit --asset USDC --amount 0.3 --broadcast +agent deposit --asset USDC --amount 0.3 --broadcast # Filter by protocol -polygon-agent deposit --asset USDC --amount 0.3 --protocol aave --broadcast -polygon-agent deposit --asset USDC --amount 0.3 --protocol morpho --broadcast +agent deposit --asset USDC --amount 0.3 --protocol aave --broadcast +agent deposit --asset USDC --amount 0.3 --protocol morpho --broadcast ``` ### Supported Protocols @@ -176,51 +173,16 @@ Pass the **position token** you hold: an **Aave aToken** address, or a **Morpho ```bash # Full exit from an Aave position (aToken from balances output) -polygon-agent withdraw --position 0x68215b6533c47ff9f7125ac95adf00fe4a62f79e --amount max --chain mainnet +agent withdraw --position 0x68215b6533c47ff9f7125ac95adf00fe4a62f79e --amount max --chain mainnet # Partial Aave withdraw (underlying units, e.g. USDC) -polygon-agent withdraw --position --amount 0.5 --chain mainnet --broadcast +agent withdraw --position --amount 0.5 --chain mainnet --broadcast # ERC-4626: max redeems all shares; partial amount is underlying units (convertToShares) -polygon-agent withdraw --position --amount max --chain polygon --broadcast +agent withdraw --position --amount max --chain polygon --broadcast ``` -Whitelist the **pool** (Aave) or **vault** contract on the session if the wallet rejects the call (`polygon-agent wallet create --contract `). - -**Same chain as the transaction:** if you use `withdraw --chain mainnet`, create or refresh the session with **`wallet create --chain mainnet`** (not only Polygon defaults). Include **`--contract`** for the **pool** and for the **underlying ERC-20** on that chain (e.g. mainnet USDC `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48`) so fee / helper transfers are allowed. Tight **`--usdc-limit`** can block those — omit or relax for yield exits. - -### Session Whitelisting - -If the deposit is rejected with a session permission error, both the token contract and the pool deposit contract must be whitelisted in the session: - -```bash -# 1. Dry-run first — output includes both addresses under `transactions[0].to` (token) and `depositAddress` (pool) -polygon-agent deposit --asset USDC --amount 0.3 -# → note the token contract address (e.g. USDC: 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359) -# → note the depositAddress (e.g. Aave V3: 0x794a61358d6845594f94dc1db02a252b5b4814ad) - -# 2. Re-create wallet session with BOTH contracts whitelisted -polygon-agent wallet create --contract --contract - -# 3. Retry -polygon-agent deposit --asset USDC --amount 0.3 --broadcast -``` - -Contracts auto-whitelisted in every session (no `--contract` flag needed): -- USDC: `0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359` -- USDC.e: `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174` -- Aave V3 Pool: `0x794a61358d6845594f94dc1db02a252b5b4814ad` - -### Yield Vault Contract Whitelist - -#### Polygon Mainnet (chainId 137) - -| Protocol | Asset | Address | -|----------|-------|---------| -| Aave V3 Pool (all markets) | USDC, USDT, WETH, WMATIC… | `0x794a61358d6845594f94dc1db02a252b5b4814ad` | -| Morpho Compound USDC | USDC | `0x781fb7f6d845e3be129289833b04d43aa8558c42` | -| Morpho Compound WETH | WETH | `0xf5c81d25ee174d83f1fd202ca94ae6070d073ccf` | -| Morpho Compound POL | POL | `0x3f33f9f7e2d7cfbcbdf8ea8b870a6e3d449664c2` | +The embedded wallet can call the pool or vault on any chain, so no contract authorization is needed — just make sure the wallet holds a little POL or USDC on that chain for gas. To withdraw on a chain other than Polygon, pass `--chain mainnet` (or another supported chain) on the `withdraw` command itself. --- @@ -228,32 +190,35 @@ Contracts auto-whitelisted in every session (no `--contract` flag needed): ```bash # 1. Check balances -polygon-agent balances +agent balances # 2. Swap POL → USDC -polygon-agent swap --from POL --to USDC --amount 1 --broadcast +agent swap --from POL --to USDC --amount 1 --broadcast # 3. Deposit USDC into highest-TVL yield pool -polygon-agent deposit --asset USDC --amount 1 --broadcast +agent deposit --asset USDC --amount 1 --broadcast # → protocol: morpho (or aave, whichever has highest TVL at the time) # → poolApy shown in dry-run output # 4. Bridge remaining USDC to Arbitrum -polygon-agent swap --from USDC --to USDC --amount 0.5 --to-chain arbitrum --broadcast +agent swap --from USDC --to USDC --amount 0.5 --to-chain arbitrum --broadcast ``` --- -## wallet create — Key Options +## Arbitrary Contract Calls -| Flag | Purpose | -|------|---------| -| `--usdc-limit ` | Enable USDC gas paymaster. Required when the wallet has no POL. Recommended: `--usdc-limit 50`. | -| `--contract ` | Whitelist an additional contract (repeatable). Use this if a deposit is rejected due to a missing contract permission. | +For any operation not covered by the dedicated commands, use `call` to send a raw transaction to any contract (the embedded wallet can call anything): ```bash -# New session with USDC gas enabled -polygon-agent wallet create --usdc-limit 50 +# Dry-run an arbitrary call +agent call --to 0x... --data 0x... + +# With an attached native value, then broadcast +agent call --to 0x... --data 0x... --value 0.1 --broadcast + +# For a native-only wallet, force the relayer to take its fee in POL +agent call --to 0x... --data 0x... --prefer-native-fee --broadcast ``` --- @@ -262,9 +227,9 @@ polygon-agent wallet create --usdc-limit 50 | Error | Cause | Fix | |-------|-------|-----| -| `Insufficient : wallet has X` | Balance too low for the requested deposit amount | Run `polygon-agent balances` and adjust `--amount` | -| `Wallet has no POL for gas` | No native gas and no USDC paymaster | Fund with POL (`polygon-agent fund`) or re-create session with `--usdc-limit 50` | -| `Transaction rejected by relay` | Session permissions missing for pool or token contract | Re-create with `--contract --contract ` | -| `Unable to pay gas` | No usable fee token found | Fund with POL or add `--usdc-limit 50` to session | -| `Protocol X not yet supported` | Trails returned a protocol other than aave/morpho | Use `polygon-agent swap` to obtain the yield-bearing token manually | +| `Not logged in` / no wallet found | No active wallet session | Run `agent wallet login` | +| Session expired | Sessions last about a week | Run `agent wallet login` | +| `Insufficient : wallet has X` | Balance too low for the requested deposit amount | Run `agent balances` and adjust `--amount` | +| `Unable to pay gas` / `Wallet has no POL for gas` | Wallet can't cover the relayer fee in USDC or POL | Fund the wallet with a little POL or USDC; for a native-only wallet, pass `--prefer-native-fee` on `call` | +| `Protocol X not yet supported` | Trails returned a protocol other than aave/morpho | Use `agent swap` to obtain the yield-bearing token manually | | `swap`: no route found | Insufficient liquidity for the pair | Try a different amount or token pair | diff --git a/skills/polygon-discovery/SKILL.md b/skills/polygon-discovery/SKILL.md index 7fb390d..07eed82 100644 --- a/skills/polygon-discovery/SKILL.md +++ b/skills/polygon-discovery/SKILL.md @@ -1,126 +1,170 @@ --- name: polygon-discovery -description: x402 Bazaar — pay-per-call API services accessible via the Polygon Agent CLI. No API keys or subscriptions needed. Each call costs a small USDC amount drawn from the agent's smart wallet. Covers web search, news, AI image generation, Twitter/X data, code review, text summarization, sentiment analysis, and article extraction. +description: Agentic Services on Polygon — pay-per-call APIs gated by the x402 payment protocol, callable via the Polygon Agent CLI. No API keys or subscriptions; each call costs a small USDC amount drawn from the agent's smart wallet. Covers web search (Exa, SearchApi), web scraping (Firecrawl), news (NewsAPI), LLM inference (Llama 3.3/3.2 via NVIDIA NIM, OpenRouter), cloud browsers (Browserbase), email (Resend, AgentMail), on-chain wallet analytics and prices (Allium), and multi-chain JSON-RPC (QuickNode, 16 chains). --- -# x402 Bazaar Services +# Agentic Services (x402) -Pay-per-call APIs accessible via `x402-pay`. No API keys or subscriptions — each call costs a small USDC amount drawn from your wallet. The CLI detects the 402 response, funds the exact amount, and retries automatically. +Pay-per-call APIs on the **Agentic Services** marketplace, gated by the x402 payment +protocol on Polygon mainnet. No API keys or subscriptions — each call costs a small +USDC amount drawn from your wallet. The CLI (`x402-pay`) detects the `402` response, +signs the exact payment, and retries automatically. -**Catalog:** `GET https://x402-api.onrender.com/api/catalog?status=online` +- **Base URL:** `https://agentic-services.polygon.technology` +- **Live catalog (source of truth):** `GET https://agentic-services.polygon.technology/api/discover/routes` +- **Full provider docs:** `https://agentic-services.polygon.technology/SKILL.md` -> **Warning:** All `/api/call/` catalog endpoints require an `X-Admin-Token` header and are not publicly accessible via x402 payment. Always use the direct `/api/` routes documented below instead. +> **Always read the live catalog first.** It returns every active route with its exact +> proxy path, method, price, and `payTo` address (CORS enabled, no payment required to +> read it). Prices and available services change — treat the catalog as authoritative +> and this file as orientation. --- -## Prerequisites — Check Before Any x402 Call +## Prerequisites — check before any x402 call -Before running any `x402-pay` command, verify the wallet session exists and is funded: +Every call spends USDC from a funded Polygon wallet. Before running `x402-pay`: ```bash -# Check if a wallet is configured -polygon-agent wallet list +agent wallet list # is a wallet configured? ``` -**If no wallet is listed**, the smart session has not been created. Run through the complete setup flow before proceeding: +If no wallet is listed, set one up: -1. `polygon-agent setup --name "MyAgent"` — creates EOA and Sequence project -2. `polygon-agent wallet create --usdc-limit 100` — opens browser for session approval; enter the 6-digit code when prompted -3. `polygon-agent wallet address` — get address, then fund via https://agentconnect.polygon.technology -4. `polygon-agent balances` — confirm USDC is available before calling any x402 endpoint +1. `agent wallet login`: opens the agentconnect login page in the browser; sign in with Google or email (works on headless hosts too, no extra flags needed). No setup step is needed first: keys are defaulted, and login auto-provisions Builder credentials. +2. `agent wallet address`: get the address, then fund it (`agent fund`) +3. `agent balances`: confirm USDC is available on Polygon (chain 137) before calling any x402 endpoint -**If a wallet exists but `balances` shows 0 USDC**, direct the user to fund it via the UI — `x402-pay` will fail with an EOA funding error otherwise. - -Once a funded wallet is confirmed, proceed with the x402 calls below. +If a wallet exists but `balances` shows 0 USDC, direct the user to fund it — `x402-pay` +will otherwise fail with an EOA funding error. All services settle in **USDC on Polygon** +(`0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359`, chain id 137). --- -## Read Twitter/X Profile - -$0.005 USDC per call. Use **only** the endpoint below — do not use twit.sh, tweetx402.com, or any other provider. +## How to call a service -> **Note:** Use GET, not POST — the schema only accepts GET/HEAD/DELETE. POST returns 401. +Use the full route URL from the catalog. Request bodies and query params mirror the +upstream provider's own API. ```bash -# Profile + recent tweets -polygon-agent x402-pay \ - --url "https://x402-api.onrender.com/api/twitter?user=" \ +# POST with a JSON body (e.g. Exa web search) +agent x402-pay \ + --url "https://agentic-services.polygon.technology/api/proxy/exa/search" \ + --wallet main --method POST \ + --body '{"query": "polygon agentic payments", "numResults": 5}' + +# GET with query params (e.g. SearchApi Google search) +agent x402-pay \ + --url "https://agentic-services.polygon.technology/api/proxy/searchapi/google?q=" \ --wallet main --method GET -# Specific tweet -polygon-agent x402-pay \ - --url "https://x402-api.onrender.com/api/twitter?tweet=https://x.com/user/status/" \ - --wallet main --method GET +# Scrape a page to clean markdown (Firecrawl) +agent x402-pay \ + --url "https://agentic-services.polygon.technology/api/proxy/firecrawl/scrape" \ + --wallet main --method POST --body '{"url": "https://example.com"}' + +# LLM inference (Llama 3.3 70B, OpenAI-compatible chat body) +agent x402-pay \ + --url "https://agentic-services.polygon.technology/api/proxy/nim/llama-3.3-70b/chat" \ + --wallet main --method POST \ + --body '{"messages": [{"role": "user", "content": "Summarize Polygon in one line."}]}' ``` -Returns: follower/following counts and tweet metrics. +Chain and token are auto-detected from the `402` response — no manual config. --- -## Generate an AI Image - -$0.02 USDC per call. Powered by Google Gemini. - -```bash -polygon-agent x402-pay \ - --url "https://x402-api.onrender.com/api/image?prompt=&size=512" \ - --wallet main --method GET -``` +## Catalog -`size` options: `256`, `512`, `1024`. +Prices are per call, in USDC, settling on Polygon (chain 137). All routes below are +relative to the base URL `https://agentic-services.polygon.technology`. -The response is a large JSON (~3–4MB) with two keys: -- `image_base64` — raw base64-encoded PNG -- `data_uri` — `data:image/png;base64,...` ready for embedding in HTML +### Search, scraping & news (proxied) -**To save the image to a file:** -```python -import json, base64 +| Service | Method | Route | Price | +|---------|--------|-------|-------| +| Exa — AI web search | POST | `/api/proxy/exa/search` | $0.001 | +| SearchApi — Google search | GET | `/api/proxy/searchapi/google` | $0.001 | +| Firecrawl — scrape to markdown | POST | `/api/proxy/firecrawl/scrape` | $0.002 | +| NewsAPI — top headlines | GET | `/api/proxy/news/headlines` | $0.001 | -data = json.load(open('response.json')) -with open('output.png', 'wb') as f: - f.write(base64.b64decode(data['data']['image_base64'])) -``` +### AI inference (proxied) ---- +| Service | Method | Route | Price | +|---------|--------|-------|-------| +| NVIDIA NIM — Llama 3.3 70B (chat) | POST | `/api/proxy/nim/llama-3.3-70b/chat` | $0.01 | +| NVIDIA NIM — Llama 3.2 90B Vision (image + chat) | POST | `/api/proxy/nim/llama-3.2-vision/chat` | $0.01 | +| OpenRouter — 200+ models (GPT, Claude, Gemini, Llama…) | POST | `/api/proxy/openrouter/chat` | $0.01 | -## Review Code for Bugs & Security +### Web automation & email (proxied) -$0.01 USDC per call. Powered by GPT-4o. +| Service | Method | Route | Price | +|---------|--------|-------|-------| +| Browserbase — cloud browser session | POST | `/api/proxy/browserbase/sessions` | $0.001 | +| Resend — send transactional email | POST | `/api/proxy/resend/send` | $0.005 | -```bash -polygon-agent x402-pay \ - --url "https://x402-api.onrender.com/api/code-review" \ - --wallet main \ - --method POST \ - --body '{"code": "", "language": ""}' -``` +### On-chain data, email inboxes & RPC (external providers) -Returns: bugs, security issues, performance problems, and style suggestions — each with line number, severity, and fix suggestion. Plus an overall quality score. +These are x402-native providers: you call **their own endpoint URL directly** (not a +`/api/proxy/*` path), still settling in USDC on Polygon. `x402-pay` handles the `402` +exactly the same way. Pass the full URL below as `--url`. ---- +**QuickNode RPC** — $0.001/call, POST standard JSON-RPC. URL pattern +`https://x402.quicknode.com//`: -## Other Services +| Chain | `` slug | | Chain | `` slug | +|-------|----------------|-|-------|----------------| +| Polygon | `matic-mainnet` | | Optimism | `optimism-mainnet` | +| Polygon Amoy | `matic-amoy` | | Avalanche | `avalanche-mainnet` | +| Polygon zkEVM | `zkevm-mainnet` | | BSC | `bsc-mainnet` | +| Base | `base-mainnet` | | Linea | `linea-mainnet` | +| Ethereum | `ethereum-mainnet` | | Scroll | `scroll-mainnet` | +| Solana | `solana-mainnet` | | Sui | `sui-mainnet` | +| Arbitrum | `arbitrum-mainnet` | | TON | `ton-mainnet` | +| Bitcoin | `btc-mainnet` | | Tron | `tron-mainnet` | -| Service | Price | Endpoint | Key param | -|---------|-------|----------|-----------| -| Web search (DuckDuckGo) | $0.005 | `9b0f5b5f-8e6c-4b55-a264-008e4e490c26` | `?q=&max=10` | -| Latest news (Google News) | $0.005 | `266d045f-bae2-4c71-9469-3638ec860fc4` | `?topic=&lang=en` | -| Summarize text (GPT-4o-mini) | $0.01 | `dd9b5098-700d-47a9-a41a-c9eae66ca49d` | `?text=&maxLength=200` | -| Article → Markdown | $0.005 | `87b50238-5b99-4521-b5e1-7515a9c1526d` | `?url=` | -| Sentiment analysis (GPT-4o-mini) | $0.005 | `66d68ca6-a8d9-41a3-b024-a3fac2f5c7ba` | `?text=` | +```bash +agent x402-pay \ + --url "https://x402.quicknode.com/matic-mainnet/" \ + --wallet main --method POST \ + --body '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' +``` -All use GET via `polygon-agent x402-pay --url "https://x402-api.onrender.com/api/call/" --wallet main --method GET`. +**Allium — on-chain wallet analytics** — base `https://agents.allium.so/api/v1/developer/`: + +| Endpoint | Method | Full URL | Price | +|----------|--------|----------|-------| +| Wallet balances | POST | `…/wallet/balances` | $0.03 | +| Wallet PnL | POST | `…/wallet/pnl` | $0.03 | +| Wallet transactions | POST | `…/wallet/transactions` | $0.03 | +| Wallet balances history | POST | `…/wallet/balances/history` | $0.01 | +| Prices (latest) | POST | `…/prices` | $0.02 | +| Prices at timestamp | POST | `…/prices/at-timestamp` | $0.02 | +| Prices history | POST | `…/prices/history` | $0.02 | +| Tokens list | GET | `…/tokens` | $0.03 | +| Tokens search | GET | `…/tokens/search` | $0.03 | + +**AgentMail — email inbox for the agent** — $2/call, base `https://x402.api.agentmail.to/v0/inboxes`: + +| Endpoint | Method | Full URL | +|----------|--------|----------| +| Create inbox | POST | `https://x402.api.agentmail.to/v0/inboxes` | +| List messages | GET | `…/{inbox_id}/messages` | +| Get message | GET | `…/{inbox_id}/messages/{message_id}` | +| Send message | POST | `…/{inbox_id}/messages/send` | +| Reply message | POST | `…/{inbox_id}/messages/{message_id}/reply` | +| List threads | GET | `…/{inbox_id}/threads` | --- -## How x402 Works +## How x402 works -1. CLI sends the request to the endpoint -2. Endpoint responds with `HTTP 402 Payment Required` + payment details -3. CLI automatically funds the builder EOA with the exact token amount from the smart wallet -4. EOA signs an EIP-3009 payment authorization -5. CLI retries the original request with the payment header -6. Response is returned — the whole flow is transparent to the agent +1. CLI sends the request to the endpoint. +2. Endpoint responds with `HTTP 402 Payment Required` + payment details (price, asset, network, `payTo`). +3. CLI signs an EIP-3009 `transferWithAuthorization` for the exact amount from the wallet. +4. CLI retries the request with the payment header. +5. Endpoint verifies, calls the upstream API, returns the response; the settlement tx hash comes back in the `PAYMENT-RESPONSE` header. -Chain and token are auto-detected from the 402 response. No manual configuration needed. +The whole flow is transparent to the agent. Chain and token are auto-detected from the +`402` response. Do not guess endpoints or search the web for providers — read the live +catalog (`/api/discover/routes`) for the correct, current URLs and prices. diff --git a/skills/polygon-polymarket/SKILL.md b/skills/polygon-polymarket/SKILL.md index b5c8e62..9a18e46 100644 --- a/skills/polygon-polymarket/SKILL.md +++ b/skills/polygon-polymarket/SKILL.md @@ -10,7 +10,7 @@ description: Place bets on Polymarket prediction markets using the Polygon Agent Before any polymarket command, verify the Polymarket key is set: ```bash -polygon-agent polymarket proxy-wallet +agent polymarket proxy-wallet ``` If this returns `ok: true` with an `eoaAddress` and `proxyWalletAddress`, the key is configured and you can proceed directly to trading. If it errors, the user needs to run `set-key` (see Onboarding below). @@ -25,9 +25,9 @@ Every Polymarket user has three addresses. Do not confuse them: |------|-----------|---------| | EOA | Private key owner. Shown as `eoaAddress` in CLI output | Signs transactions and CLOB orders. Needs POL for gas only when running `approve` | | Proxy Wallet | Shown as `proxyWalletAddress` in CLI output. This is what Polymarket shows as "your address" in the UI | Holds pUSD and outcome tokens. The CLOB `maker` | -| Smart Wallet | The Sequence wallet (`polygon-agent wallet`) | Funds the proxy wallet with USDC.e per trade (auto-wrapped to pUSD) | +| Smart Wallet | The OMS wallet (`agent wallet`) | Funds the proxy wallet with USDC.e per trade (auto-wrapped to pUSD) | -**For trading:** USDC.e flows from the Sequence smart wallet → proxy wallet → auto-wrapped to pUSD → CLOB orders. The proxy wallet is the trading identity. +**For trading:** USDC.e flows from the OMS smart wallet → proxy wallet → auto-wrapped to pUSD → CLOB orders. The proxy wallet is the trading identity. --- @@ -37,7 +37,7 @@ Before placing a trade, verify these four things in order: **1. EOA key is configured** ```bash -polygon-agent polymarket proxy-wallet +agent polymarket proxy-wallet # → must return ok: true with eoaAddress and proxyWalletAddress ``` @@ -53,7 +53,7 @@ polygon-agent polymarket proxy-wallet **4. Smart wallet has USDC.e** ← required per trade, minimum $1 ```bash -polygon-agent balances +agent balances # → check USDC.e balance (0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174) # → must have at least $1 USDC.e to place any order # → USDC.e is auto-wrapped to pUSD during the buy flow @@ -74,19 +74,19 @@ polygon-agent balances **Step 2: Import the key into the CLI** ```bash -polygon-agent polymarket set-key +agent polymarket set-key ``` Output confirms the `eoaAddress` and `proxyWalletAddress`. **Step 3: Show the user their addresses** ```bash -polygon-agent polymarket proxy-wallet +agent polymarket proxy-wallet ``` Tell the user: "Your EOA is `` — this needs a small amount of POL for the one-time approval step. Your Polymarket trading address (proxy wallet) is `` — this is where your pUSD and outcome tokens live." **Step 4: Fund EOA with POL for gas (approval step only)** ```bash -polygon-agent send-native --to --amount 0.1 --broadcast +agent send-native --to --amount 0.1 --broadcast ``` The EOA only needs POL for the one-time `approve` transaction. After that, trading requires no gas from the EOA. @@ -99,7 +99,7 @@ The EOA only needs POL for the one-time `approve` transaction. After that, tradi **Step 6: Set proxy wallet approvals for V2 (one-time, permanent)** ```bash -polygon-agent polymarket approve --broadcast +agent polymarket approve --broadcast ``` This sets approvals for the V2 exchange contracts and CollateralOnramp. Permanent on-chain — never needs to be run again for this EOA. @@ -107,7 +107,7 @@ This sets approvals for the V2 exchange contracts and CollateralOnramp. Permanen **Step 1: Confirm addresses** ```bash -polygon-agent polymarket proxy-wallet +agent polymarket proxy-wallet ``` **Step 2: Accept Terms of Service (required)** @@ -119,12 +119,12 @@ polygon-agent polymarket proxy-wallet **Step 3: Fund EOA with POL for gas** ```bash -polygon-agent send-native --to --amount 0.1 --broadcast +agent send-native --to --amount 0.1 --broadcast ``` **Step 4: Set proxy wallet approvals for V2 (one-time)** ```bash -polygon-agent polymarket approve --broadcast +agent polymarket approve --broadcast ``` --- @@ -135,13 +135,13 @@ polygon-agent polymarket approve --broadcast ```bash # List top markets by volume -polygon-agent polymarket markets +agent polymarket markets # Search by keyword -polygon-agent polymarket markets --search "bitcoin" --limit 10 +agent polymarket markets --search "bitcoin" --limit 10 # Paginate -polygon-agent polymarket markets --limit 20 --offset 20 +agent polymarket markets --limit 20 --offset 20 ``` Key output fields per market: @@ -154,7 +154,7 @@ Key output fields per market: ### Get a Single Market ```bash -polygon-agent polymarket market +agent polymarket market ``` Use this to confirm prices and token IDs before placing an order. @@ -162,7 +162,7 @@ Use this to confirm prices and token IDs before placing an order. ### Show Proxy Wallet Address ```bash -polygon-agent polymarket proxy-wallet +agent polymarket proxy-wallet ``` Confirms which EOA and proxy wallet are active. The proxy wallet is where pUSD and tokens are held. @@ -171,10 +171,10 @@ Confirms which EOA and proxy wallet are active. The proxy wallet is where pUSD a ```bash # Standard markets -polygon-agent polymarket approve --broadcast +agent polymarket approve --broadcast # Neg-risk markets (only if you see negRisk: true on a market you want to trade) -polygon-agent polymarket approve --neg-risk --broadcast +agent polymarket approve --neg-risk --broadcast ``` **All users must run this after the V2 migration** — previous V1 approvals on old exchange contracts do not carry over. V2 approvals cover: pUSD → V2 exchange, CTF → V2 exchange, and USDC.e → CollateralOnramp (for wrapping). Once set, they are permanent on-chain. @@ -183,20 +183,20 @@ polygon-agent polymarket approve --neg-risk --broadcast ```bash # Dry-run first — always check before executing -polygon-agent polymarket clob-buy YES|NO +agent polymarket clob-buy YES|NO # Execute — funds proxy wallet, wraps USDC.e → pUSD, then places order -polygon-agent polymarket clob-buy YES|NO --broadcast +agent polymarket clob-buy YES|NO --broadcast # If proxy wallet already has pUSD from a previous failed order (skip the funding step) -polygon-agent polymarket clob-buy YES|NO --skip-fund --broadcast +agent polymarket clob-buy YES|NO --skip-fund --broadcast # Limit order — fill only at this price or better -polygon-agent polymarket clob-buy YES --price 0.45 --broadcast +agent polymarket clob-buy YES --price 0.45 --broadcast ``` **How it works:** -1. Smart wallet transfers `usdcAmount` USDC.e to the proxy wallet (Sequence tx) +1. Smart wallet transfers `usdcAmount` USDC.e to the proxy wallet (OMS tx) 2. Proxy wallet wraps USDC.e → pUSD via CollateralOnramp (on-chain, EOA gas) 3. Posts CLOB BUY order: maker=proxy wallet, signer=EOA (off-chain, no gas) 4. Tokens arrive in proxy wallet on fill @@ -212,13 +212,13 @@ polygon-agent polymarket clob-buy YES --price 0.45 -- ```bash # Dry-run first -polygon-agent polymarket sell YES|NO +agent polymarket sell YES|NO # Execute -polygon-agent polymarket sell YES|NO --broadcast +agent polymarket sell YES|NO --broadcast # Limit sell -polygon-agent polymarket sell YES --price 0.80 --broadcast +agent polymarket sell YES --price 0.80 --broadcast ``` `` is the number of outcome tokens (not USD). Get share count from `positions`. @@ -227,7 +227,7 @@ Selling is pure off-chain — no gas, no on-chain tx. Proceeds are received as p ### Check Positions ```bash -polygon-agent polymarket positions +agent polymarket positions ``` Shows all open positions in the proxy wallet with current value, P&L, and outcome. @@ -235,7 +235,7 @@ Shows all open positions in the proxy wallet with current value, P&L, and outcom ### Check Open Orders ```bash -polygon-agent polymarket orders +agent polymarket orders ``` Lists GTC limit orders that are still open (FOK/FAK orders are never "open" — they fill or cancel immediately). @@ -243,7 +243,7 @@ Lists GTC limit orders that are still open (FOK/FAK orders are never "open" — ### Cancel an Order ```bash -polygon-agent polymarket cancel +agent polymarket cancel ``` Get `orderId` from the `orders` command or from the `orderId` field in `clob-buy` output. @@ -256,16 +256,16 @@ Get `orderId` from the `orders` command or from the `orderId` field in `clob-buy # ── FIRST TIME (run once per EOA) ────────────────────────────────────── # 1. Import Polymarket private key -polygon-agent polymarket set-key 0x +agent polymarket set-key 0x # → save eoaAddress and proxyWalletAddress # 2. Accept ToS at https://polymarket.com (connect EOA, accept when prompted) # 3. Fund EOA with POL for the one-time approval tx -polygon-agent send-native --to --amount 0.1 --broadcast +agent send-native --to --amount 0.1 --broadcast # 4. Set V2 approvals (one-time, permanent — covers pUSD, CTF, and CollateralOnramp) -polygon-agent polymarket approve --broadcast +agent polymarket approve --broadcast # ── RETURNING USER ────────────────────────────────────────────────────── # If V2 approvals were already set: skip steps 1-4, go straight to trading. @@ -274,31 +274,31 @@ polygon-agent polymarket approve --broadcast # ── FIND A MARKET ──────────────────────────────────────────────────────── # 5. Search for markets -polygon-agent polymarket markets --search "bitcoin" --limit 10 +agent polymarket markets --search "bitcoin" --limit 10 # 6. Get details on a specific market -polygon-agent polymarket market 0x +agent polymarket market 0x # → check: yesPrice, noPrice, negRisk, endDate # → if negRisk: true → run approve --neg-risk --broadcast first # ── ENTER A POSITION ──────────────────────────────────────────────────── # 7. Dry-run to confirm -polygon-agent polymarket clob-buy 0x YES 5 +agent polymarket clob-buy 0x YES 5 # → review: currentPrice, proxyWalletAddress, flow (includes pUSD wrapping) # 8. Execute -polygon-agent polymarket clob-buy 0x YES 5 --broadcast +agent polymarket clob-buy 0x YES 5 --broadcast # → check: orderStatus === "matched" # ── MANAGE ────────────────────────────────────────────────────────────── # 9. Check positions -polygon-agent polymarket positions +agent polymarket positions # → review: size (shares), curPrice, cashPnl # 10. Sell when ready -polygon-agent polymarket sell 0x YES --broadcast +agent polymarket sell 0x YES --broadcast # → orderStatus === "matched" means pUSD is back in proxy wallet ``` @@ -327,17 +327,17 @@ When deciding whether to sell: | Error | Cause | Fix | |-------|-------|-----| -| `No EOA key found` | `set-key` not run | Run `polygon-agent polymarket set-key ` | +| `No EOA key found` | `set-key` not run | Run `agent polymarket set-key ` | | `Could not create api key` (stderr only) | ToS not accepted | Non-fatal — CLI retries with `deriveApiKey` and may still succeed. If orders fail too, visit polymarket.com and accept ToS with the EOA | | `CLOB order error: not authorized` | ToS not accepted | Visit polymarket.com, connect EOA wallet, accept terms | -| `insufficient funds for gas` | EOA has no POL | `polygon-agent send-native --to --amount 0.1 --broadcast` | +| `insufficient funds for gas` | EOA has no POL | `agent send-native --to --amount 0.1 --broadcast` | | `Market not found` | Low-volume or closed market | Market may have resolved; try `--search` with different terms | | `Market has no tokenIds` | Closed market | Check `endDate` — market resolved | | `orderStatus: "unmatched"` on FOK | No liquidity at market price | Try `--fak` for partial fill, or `--price 0.x` for limit order | | `invalid amount for a marketable BUY order ($X), min size: $1` | Amount below CLOB minimum | Use at least $1. If pUSD was already funded, retry with `--skip-fund` | -| `Wallet not found: main` | No Sequence wallet | Run `polygon-agent wallet create` | -| `No signer supported for call` | Wallet session missing USDC.e whitelist | Re-create wallet session: `polygon-agent wallet create --name main` | -| Approvals tx reverts after V2 migration | V1 approvals — wrong exchange contracts | Re-run `polygon-agent polymarket approve --broadcast` for V2 contracts | +| `Wallet not found: main` | Not logged in | Run `agent wallet login` | +| Session expired (`OMS_SESSION_EXPIRED`) | Login session lapsed (~1 week) | Run `agent wallet login` | +| Approvals tx reverts after V2 migration | V1 approvals — wrong exchange contracts | Re-run `agent polymarket approve --broadcast` for V2 contracts | --- @@ -347,7 +347,7 @@ When deciding whether to sell: - **All commands are dry-run by default.** `approve`, `clob-buy`, `sell` do nothing without `--broadcast`. - **V2 approvals are required for all users.** V1 approvals on old exchange contracts do not carry over. Run `approve --broadcast` once after migration. - **`clob-buy` handles the full flow automatically:** transfers USDC.e from smart wallet → proxy wallet, wraps USDC.e → pUSD, then places the CLOB order (unless `--skip-fund`). -- **Positions live in the proxy wallet**, not the Sequence smart wallet. `positions` queries the proxy wallet. +- **Positions live in the proxy wallet**, not the OMS smart wallet. `positions` queries the proxy wallet. - **Sell is free.** No gas, no on-chain tx. Selling via CLOB is a signed off-chain message only. Proceeds are pUSD. - **`orderStatus: "matched"`** means the trade filled. `"unmatched"` means FOK failed (no liquidity). - **Fees are protocol-determined at match time.** Makers never pay fees — only takers. No `feeRateBps` on orders. diff --git a/tsconfig.json b/tsconfig.json index 69e0152..eb081c3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,9 +2,5 @@ "extends": ["@tsconfig/node24", "@tsconfig/node-ts"], "compilerOptions": { "noEmit": true, "resolveJsonModule": true }, "files": [], - "references": [ - { "path": "packages/polygon-agent-cli" }, - { "path": "packages/connector-ui" }, - { "path": "packages/shared" } - ] + "references": [{ "path": "packages/polygon-agent-cli" }] }