diff --git a/.github/workflows/publish_npm_coinbase_x402.yml b/.github/workflows/publish_npm_coinbase_x402.yml deleted file mode 100644 index 319b7b84a..000000000 --- a/.github/workflows/publish_npm_coinbase_x402.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Publish coinbase-x402 package to NPM - -on: - workflow_dispatch: - -jobs: - publish-npm-coinbase-x402: - runs-on: ubuntu-latest - environment: ${{ github.ref == 'refs/heads/main' && 'npm' || '' }} - permissions: - contents: read - id-token: write - steps: - - uses: actions/checkout@v4 - - - name: Setup pnpm - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda - with: - version: 10.7.0 - - - uses: actions/setup-node@v4 - with: - node-version: "20" - registry-url: "https://registry.npmjs.org" - cache: "pnpm" - cache-dependency-path: ./typescript - - - name: Install and build - working-directory: ./typescript - run: | - pnpm install --frozen-lockfile - pnpm -r --filter=x402 --filter=@coinbase/x402 run build - - - name: Publish coinbase-x402 package - working-directory: ./typescript/packages/coinbase-x402 - run: | - # Get package information directly - PACKAGE_NAME=$(node -p "require('./package.json').name") - PACKAGE_VERSION=$(node -p "require('./package.json').version") - - echo "Package: $PACKAGE_NAME@$PACKAGE_VERSION" - - # Check if running on main branch - if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then - echo "Publishing to NPM (main branch)" - pnpm publish --provenance --access public - else - echo "Dry run only (non-main branch: ${{ github.ref }})" - pnpm publish --dry-run --no-git-checks - fi - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/publish_npm_x402.yml b/.github/workflows/publish_npm_x402.yml index 3bde5dab2..d007f8b52 100644 --- a/.github/workflows/publish_npm_x402.yml +++ b/.github/workflows/publish_npm_x402.yml @@ -32,7 +32,7 @@ jobs: pnpm -r --filter=x402 run build - name: Publish x402 package - working-directory: ./typescript/packages/x402 + working-directory: ./typescript/packages/legacy/x402 run: | # Get package information directly PACKAGE_NAME=$(node -p "require('./package.json').name") diff --git a/.github/workflows/publish_npm_x402_axios.yml b/.github/workflows/publish_npm_x402_axios.yml index 824a5289d..35bf3ad05 100644 --- a/.github/workflows/publish_npm_x402_axios.yml +++ b/.github/workflows/publish_npm_x402_axios.yml @@ -32,7 +32,7 @@ jobs: pnpm -r --filter=x402 --filter=x402-axios run build - name: Publish x402-axios package - working-directory: ./typescript/packages/x402-axios + working-directory: ./typescript/packages/legacy/x402-axios run: | # Get package information directly PACKAGE_NAME=$(node -p "require('./package.json').name") diff --git a/.github/workflows/publish_npm_x402_express.yml b/.github/workflows/publish_npm_x402_express.yml index 385fc63a3..e395e436d 100644 --- a/.github/workflows/publish_npm_x402_express.yml +++ b/.github/workflows/publish_npm_x402_express.yml @@ -32,7 +32,7 @@ jobs: pnpm -r --filter=x402 --filter=x402-express run build - name: Publish x402-express package - working-directory: ./typescript/packages/x402-express + working-directory: ./typescript/packages/legacy/x402-express run: | # Get package information directly PACKAGE_NAME=$(node -p "require('./package.json').name") diff --git a/.github/workflows/publish_npm_x402_fetch.yml b/.github/workflows/publish_npm_x402_fetch.yml index 471e9722c..c7470dfa3 100644 --- a/.github/workflows/publish_npm_x402_fetch.yml +++ b/.github/workflows/publish_npm_x402_fetch.yml @@ -32,7 +32,7 @@ jobs: pnpm -r --filter=x402 --filter=x402-fetch run build - name: Publish x402-fetch package - working-directory: ./typescript/packages/x402-fetch + working-directory: ./typescript/packages/legacy/x402-fetch run: | # Get package information directly PACKAGE_NAME=$(node -p "require('./package.json').name") diff --git a/.github/workflows/publish_npm_x402_hono.yml b/.github/workflows/publish_npm_x402_hono.yml index 6529c3bb9..aac955461 100644 --- a/.github/workflows/publish_npm_x402_hono.yml +++ b/.github/workflows/publish_npm_x402_hono.yml @@ -26,7 +26,7 @@ jobs: pnpm -r --filter=x402 --filter=x402-hono run build - name: Publish x402-hono package - working-directory: ./typescript/packages/x402-hono + working-directory: ./typescript/packages/legacy/x402-hono run: | # Get package information directly PACKAGE_NAME=$(node -p "require('./package.json').name") diff --git a/.github/workflows/publish_npm_x402_next.yml b/.github/workflows/publish_npm_x402_next.yml index ddde392ee..7ca52117a 100644 --- a/.github/workflows/publish_npm_x402_next.yml +++ b/.github/workflows/publish_npm_x402_next.yml @@ -26,7 +26,7 @@ jobs: pnpm -r --filter=x402 --filter=x402-next run build - name: Publish x402-next package - working-directory: ./typescript/packages/x402-next + working-directory: ./typescript/packages/legacy/x402-next run: | # Get package information directly PACKAGE_NAME=$(node -p "require('./package.json').name") diff --git a/.gitignore b/.gitignore index 9dc1c8ff9..7aefba8f3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ proxy .env __pycache__/ **/.DS_Store +e2e/facilitators/external-proxies/* +!e2e/facilitators/external-proxies/README.md \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a41ccc96..9349bdc4a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,27 +1,171 @@ # Contributing -x402 welcomes contributions of schemes, middleware, new chain support, and more. -CDP aims to make x402 as secure and trusted as possible. -Merging contributions is at the discretion of the CDP Engineering team, based on the risk of the contribution and the quality of implementation. +x402 welcomes contributions of schemes, middleware, new chain support, and more. We aim to make x402 as secure and trusted as possible. Merging contributions is at the discretion of the x402 Foundation team, based on the risk of the contribution and the quality of implementation. -If you update the core x402 Typescript package, you'll need to rebuild the paywall via `pnpm build:paywall` and commit the resulting generated files as part of your PR. +## Contents -You will also need to sign all of your commits for any contributions to be merged. +- [Repository Structure](#repository-structure) +- [Language-Specific Guides](#language-specific-guides) +- [Contributing Workflow](#contributing-workflow) +- [Commit Signing](#commit-signing) +- [Getting Help](#getting-help) -## Middleware and language libraries +## Repository Structure -Language libraries should implement best practices of the language they target, have tests, linting, and follow best practices for x402 client development. +The x402 repository contains implementations in multiple languages plus protocol specifications. + +``` +x402/ +├── typescript/ # TypeScript SDK (pnpm monorepo) +├── python/ # Python SDK +├── go/ # Go SDK +├── java/ # Java SDK +├── specs/ # Protocol specifications +└── examples/ # Example implementations + ├── typescript/ + ├── python/ + └── go/ +``` + +## Language-Specific Guides + +For setup instructions, development workflow, and contribution patterns for each SDK: + +- [TypeScript Development Guide](typescript/CONTRIBUTING.md) +- [Python Development Guide](python/CONTRIBUTING.md) +- [Go Development Guide](go/CONTRIBUTING.md) +- [Specifications Guide](specs/CONTRIBUTING.md) + +## Contributing Workflow + +### 1. Find or Create an Issue + +Check existing issues before starting work. For larger features, open a discussion first. + +### 2. Fork and Clone + +Fork the repository and clone your fork locally. + +### 3. Create a Branch + +```bash +git checkout -b feature/your-feature-name +``` + +### 4. Make Changes + +- Follow the language-specific development guide +- Write tests for new functionality +- Update documentation as needed + +### 5. Test + +Run tests for the packages you modified: + +```bash +# TypeScript +cd typescript && pnpm test + +# Python +cd python/x402 && uv run pytest + +# Go +cd go && make test +``` + +### 6. Submit PR + +- Fill out the PR template completely +- Link related issues +- Ensure CI passes + +## Commit Signing + +All commits must be [signed](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits). Configure commit signing before submitting: + +```bash +git config --global commit.gpgsign true +``` + +## Paywall Changes + +The paywall is a browser UI component that exists across TypeScript, Go, and Python. If you modify paywall source files in TypeScript: + +```bash +cd typescript && pnpm --filter @x402/paywall build:paywall +``` + +This generates template files in: +- `typescript/packages/http/paywall/src/evm/gen/template.ts` +- `typescript/packages/http/paywall/src/svm/gen/template.ts` +- `go/http/evm_paywall_template.go` +- `go/http/svm_paywall_template.go` +- `python/x402/src/x402/evm_paywall_template.py` +- `python/x402/src/x402/svm_paywall_template.py` + +Commit the generated files with your PR. ## New Schemes -Schemes dictate how funds are moved from client to server address. As such they will be thoroughly audited by CDP legal and security teams to ensure they are safe and do not put any parties in a compromising position. +Schemes dictate how funds are moved from client to server. New schemes require thorough review by the x402 Foundation team. -We recommend first proposing a scheme by opening a PR with a proposed spec into `specs/`, discussing the architecture and purpose in that PR, then once the PR is merged, moving on to implementation. +Recommended approach: + +1. Propose a scheme by opening a PR with a spec in `specs/schemes/` +2. Discuss the architecture and purpose in that PR +3. Once the spec is merged, proceed to implementation + +See [specs/CONTRIBUTING.md](specs/CONTRIBUTING.md) for spec writing guidelines. ## New Chains -We want x402 to be chain agnostic, and as such deeply appreciate implementations of new chains. +x402 aims to be chain-agnostic. New chain implementations are welcome. + +Because different chains have different best practices, a scheme may have a different mechanism on a new chain than it does on EVM. If the scheme mechanism varies from the reference implementation, the x402 Foundation will re-audit the scheme for that chain before accepting. + +### Required Interfaces + +Each language SDK defines interfaces that chain mechanisms must implement: + +**TypeScript** (`@x402/core`): +- `SchemeNetworkClient` - Signs payment payloads +- `SchemeNetworkServer` - Validates payment requirements +- `SchemeNetworkFacilitator` - Verifies and settles payments + +**Go** (`github.com/coinbase/x402/go`): +- `ClientScheme` - Signs payment payloads +- `ServerScheme` - Validates payment requirements +- `FacilitatorScheme` - Verifies and settles payments + +**Python** (`x402`): +- Implement signing in `src/x402/your_chain.py` +- Integrate with the base client in `src/x402/clients/base.py` + +See the language-specific guides for detailed implementation patterns. + +## Middleware and HTTP Integrations + +HTTP middleware packages should: + +- Follow best practices for the target framework +- Include tests +- Follow x402 client/server patterns from existing middleware + +## Examples + +Examples for each SDK live in `examples/`: + +``` +examples/ +├── typescript/ # TypeScript examples +├── python/ # Python examples +└── go/ # Go examples +``` + +When adding a new example, follow the patterns in the language-specific guide. -Because some chains have different best practices than the EVM, a logical scheme may have a different mechanism to achieve its goal than that scheme has on the EVM. +## Getting Help -If scheme mechanism for a chain must vary from the first implementation of a scheme, CDP will re-audit the scheme for that chain before accepting. +- Search existing issues +- Open a new issue with questions +- Check the language-specific guides for common patterns diff --git a/ROADMAP.md b/ROADMAP.md index f3ac54b52..dc130b421 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -13,7 +13,7 @@ This roadmap shares what the x402 team is building now, what's next, and where t * Pick a "Community" item below, then **open a GitHub Issue in this repo** with the title: `Roadmap: — Contribution Proposal`. * In your issue, include: goals, approach/design sketch, deliverables, estimated timeline, and how you'll demo/measure success. -* The CDP team will **review and offer consulting** (design feedback, API guidance, intros) so you can ship confidently. +* The team will **review and offer consulting** (design feedback, API guidance, intros) so you can ship confidently. * Docs are credibly neutral and community‑owned: contribute guides, templates, and examples to the GitBook repo → [https://github.com/murrlincoln/x402-gitbook](https://github.com/murrlincoln/x402-gitbook) (PRs welcome). @@ -149,7 +149,7 @@ If you want to contribute, these items are especially well‑scoped for communit 1. Open a GitHub Issue titled `Roadmap: — Contribution Proposal`. 2. Include problem, proposed approach, milestones/deliverables, and demo plan. -3. We'll respond with feedback and assign a CDP point‑of‑contact for consulting. +3. We'll respond with feedback and assign a point‑of‑contact for consulting. --- diff --git a/e2e/.env-local b/e2e/.env-local new file mode 100644 index 000000000..d5cfb089e --- /dev/null +++ b/e2e/.env-local @@ -0,0 +1,7 @@ +# E2E Test Configuration +SERVER_EVM_ADDRESS= +SERVER_SVM_ADDRESS= +CLIENT_EVM_PRIVATE_KEY= +CLIENT_SVM_PRIVATE_KEY= +FACILITATOR_EVM_PRIVATE_KEY= +FACILITATOR_SVM_PRIVATE_KEY= diff --git a/e2e/README.md b/e2e/README.md index 7df3f2410..8a3f7b0f5 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -2,87 +2,125 @@ End-to-end test suite for validating client-server-facilitator communication across languages and frameworks. -## Environment Variables +## Setup -Required: -- `ADDRESS`: Server wallet address -- `PRIVATE_KEY`: Client private key (when running single client) +### First Time Setup -## Quick Start +Install all dependencies (TypeScript via pnpm, Go, Python): ```bash -# Full suite -pnpm test # Run all tests +pnpm install:all +``` -# Development mode (recommended) -pnpm test -d # Test on testnet -pnpm test -d -v # Test with verbose logging +This will: +1. Install TypeScript dependencies via `pnpm install` +2. Run `install.sh` and `build.sh` for all clients, servers, and facilitators +3. Handle nested directories (like `external-proxies/` and `local/`) -# Language filters -pnpm test -d -ts # Test TypeScript implementations -pnpm test -d -py # Test Python implementations -pnpm test -d -go # Test Go implementations +For legacy (v1) implementations as well: + +```bash +pnpm install:all:legacy ``` -## Filtering Tests +### Individual Setup + +If you only want to set up v2 implementations: -### Implementation Filters ```bash ---client= # Test specific client ---server= # Test specific server +pnpm setup +``` -# Available implementations -Clients: httpx, axios, fetch, requests -Servers: express, fastapi, flask, gin, hono, next +Or manually for a specific component: -# Examples -pnpm test -d -ts --client=axios # Test TypeScript axios client -pnpm test -d -py --server=fastapi # Test Python FastAPI server +```bash +cd facilitators/go +bash install.sh +bash build.sh ``` -### Language Flags (can combine) -```bash --ts, --typescript # TypeScript implementations --py, --python # Python implementations --go, --go # Go implementations +## Usage + +### Interactive Test Mode -# Examples -pnpm test -ts -py # Test TypeScript and Python together -pnpm test -py -go # Test Python and Go together +```bash +pnpm test ``` -### Environment Filters +Launches an interactive CLI where you can select: +- **Facilitators** - Payment verification/settlement services (Go, TypeScript) +- **Servers** - Protected endpoints requiring payment (Express, Gin, Hono, Next.js, FastAPI, Flask, etc.) +- **Clients** - Payment-capable HTTP clients (axios, fetch, httpx, requests, etc.) +- **Extensions** - Additional features like Bazaar discovery +- **Protocols** - EVM and/or SVM networks + +Every valid combination of your selections will be tested. For example, selecting 2 facilitators, 3 servers, and 2 clients will generate and run all compatible test scenarios. + +### Minimized Test Mode + ```bash ---network= # base or base-sepolia ---prod= # true=CDP facilitator, false=no CDP +pnpm test --min +``` -# Examples -pnpm test --prod=true # Test production scenarios -pnpm test --network=base # Test on base network +Same interactive CLI, but with intelligent test minimization: +- **90% fewer tests** compared to full mode +- Each selected component is tested at least once across all variations +- Skips redundant combinations that provide no additional coverage +- Example: `legacy-hono` (v1 only) tests once, while `express` (v1+v2, EVM+SVM) tests all 4 combinations + +Perfect for rapid iteration during development while maintaining comprehensive coverage. + +### Verbose Logging + +```bash +pnpm test -v +pnpm test --min -v ``` -### Common Workflows +Add the `-v` flag to any command for verbose output: +- Prints all facilitator logs +- Prints all server logs +- Prints all client logs +- Shows detailed information after each test scenario + +Useful for debugging test failures or understanding the payment flow. + +## Environment Variables + +Required environment variables (set in `.env` file): ```bash -# Local Development -pnpm test -d -ts # TypeScript development -pnpm test -d -py # Python development -pnpm test -d -ts --server=next # Next.js middleware development -pnpm test -d -py --client=httpx # Python httpx client development - -# Cross-Language Testing -pnpm test -ts -py # Test TypeScript/Python compatibility -pnpm test -d -py -go # Test Python/Go on testnet - -# Production Testing -pnpm test --prod=true -ts # Test TypeScript in production -pnpm test --network=base -py # Test Python on base network +# Client wallets +CLIENT_EVM_PRIVATE_KEY=0x... # EVM private key for client payments +CLIENT_SVM_PRIVATE_KEY=... # Solana private key for client payments + +# Server payment addresses +SERVER_EVM_ADDRESS=0x... # Where servers receive EVM payments +SERVER_SVM_ADDRESS=... # Where servers receive Solana payments + +# Facilitator wallets (for payment verification/settlement) +FACILITATOR_EVM_PRIVATE_KEY=0x... # EVM private key for facilitator +FACILITATOR_SVM_PRIVATE_KEY=... # Solana private key for facilitator ``` -### Environment Options +## Example Session ```bash --d, --dev # Development mode (testnet, no CDP) --v, --verbose # Detailed logging ---log-file= # Save output to file +$ pnpm test --min + +🎯 Interactive Mode +================== + +✔ Select facilitators › go, typescript +✔ Select servers › express, hono, legacy-express +✔ Select clients › axios, fetch, httpx +✔ Select extensions › bazaar +✔ Select protocol families › EVM, SVM + +📊 Coverage-Based Minimization +Total scenarios: 156 +Selected scenarios: 18 (88.5% reduction) + +✅ Passed: 18 +❌ Failed: 0 ``` diff --git a/e2e/clients/axios/README.md b/e2e/clients/axios/README.md index 4bb308ba9..463fb72b1 100644 --- a/e2e/clients/axios/README.md +++ b/e2e/clients/axios/README.md @@ -1,80 +1,118 @@ -# x402-axios Example Client +# E2E Test Client: TypeScript Fetch -This is an example client that demonstrates how to use the `x402-axios` package to make HTTP requests to endpoints protected by the x402 payment protocol. +This client demonstrates and tests the `@x402/fetch` package with both EVM and SVM payment support. -## Prerequisites +## What It Tests -- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) -- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) -- A running x402 server (you can use the example express server at `examples/typescript/servers/express`) -- A valid Ethereum private key for making payments +### Core Functionality +- ✅ **V2 Protocol** - Modern x402 protocol with CAIP-2 networks +- ✅ **V1 Protocol** - Legacy x402 protocol with simple network names +- ✅ **Multi-chain Support** - Both EVM and SVM in a single client +- ✅ **Automatic Payment Handling** - Transparent 402 response handling +- ✅ **Payment Response Decoding** - Extracts settlement information from headers -## Setup +### Payment Mechanisms +- ✅ **EVM V2** - `eip155:*` wildcard scheme +- ✅ **EVM V1** - `base-sepolia` and `base` networks +- ✅ **SVM V2** - `solana:*` wildcard scheme +- ✅ **SVM V1** - `solana-devnet` and `solana` networks -1. Install and build all packages from the typescript examples root: -```bash -cd ../../ -pnpm install -pnpm build -cd clients/axios -``` +## What It Demonstrates -2. Copy `.env-local` to `.env` and add your Ethereum private key (remember it should have USDC on Base Sepolia, which you can provision using the [CDP Faucet](https://portal.cdp.coinbase.com/products/faucet)): -```bash -cp .env-local .env -``` +### Usage Pattern -3. Start the example client (remember you need to be running a server locally or point at an endpoint): -```bash -pnpm dev +```typescript +import { wrapFetchWithPayment } from "@x402/fetch"; +import { x402Client } from "@x402/core/client"; +import { ExactEvmClient } from "@x402/evm"; +import { ExactEvmClientV1 } from "@x402/evm/v1"; +import { ExactSvmClient } from "@x402/svm"; +import { ExactSvmClientV1 } from "@x402/svm/v1"; + +// Build x402 client with direct registration +const client = new x402Client() + .register("eip155:*", new ExactEvmClient(evmAccount)) + .register("solana:*", new ExactSvmClient(svmSigner)) + .registerV1("base-sepolia", new ExactEvmClientV1(evmAccount)) + .registerV1("base", new ExactEvmClientV1(evmAccount)) + .registerV1("solana-devnet", new ExactSvmClientV1(svmSigner)) + .registerV1("solana", new ExactSvmClientV1(svmSigner)); + +// Wrap fetch with payment handling +const fetchWithPayment = wrapFetchWithPayment(fetch, client); + +// Make request - 402 responses handled automatically +const response = await fetchWithPayment(url, { method: "GET" }); ``` -## How It Works +### Key Concepts Shown -The example demonstrates how to: -1. Create a wallet client using viem -2. Create an Axios instance with x402 payment handling -3. Make a request to a paid endpoint -4. Handle the response or any errors +1. **Builder Pattern** - Fluent API for registering multiple schemes +2. **Multi-Version Support** - V1 and V2 protocols side-by-side +3. **Multi-Chain Support** - EVM and SVM in one client +4. **Network Flexibility** - Wildcards for V2, specific networks for V1 +5. **Transparent Payment** - No manual 402 handling needed -## Example Code +## Test Scenarios -```typescript -import { config } from "dotenv"; -import { createWalletClient, http, publicActions } from "viem"; -import { privateKeyToAccount } from "viem/accounts"; -import { withPaymentInterceptor } from "x402-axios"; -import axios from "axios"; -import { baseSepolia } from "viem/chains"; - -config(); - -const { RESOURCE_SERVER_URL, PRIVATE_KEY, ENDPOINT_PATH } = process.env; - -// Create wallet client -const account = privateKeyToAccount(PRIVATE_KEY as "0x${string}"); -const client = createWalletClient({ - account, - transport: http(), - chain: baseSepolia, -}).extend(publicActions); - -// Create Axios instance with payment handling -const api = withPaymentInterceptor( - axios.create({ - baseURL: RESOURCE_SERVER_URL, - }), - client -); - -// Make request to paid endpoint -api - .get(ENDPOINT_PATH) - .then(response => { - console.log(response.headers); - console.log(response.data); - }) - .catch(error => { - console.error(error.response?.data?.error); - }); +This client is tested against: +- **Servers:** Express (TypeScript), Gin (Go) +- **Facilitators:** TypeScript, Go +- **Endpoints:** `/protected` (EVM), `/protected-svm` (SVM) +- **Networks:** Base Sepolia (EVM), Solana Devnet (SVM) + +### Success Criteria +- ✅ Request succeeds with 200 status +- ✅ Payment response header present +- ✅ Transaction hash returned +- ✅ Payment marked as successful + +## Running + +```bash +# Via e2e test suite +cd e2e +pnpm test --client=fetch + +# Direct execution (requires environment variables) +cd e2e/clients/fetch +export RESOURCE_SERVER_URL="http://localhost:4022" +export ENDPOINT_PATH="/protected" +export EVM_PRIVATE_KEY="0x..." +export SVM_PRIVATE_KEY="..." +pnpm start ``` + +## Environment Variables + +- `RESOURCE_SERVER_URL` - Server base URL +- `ENDPOINT_PATH` - Path to protected endpoint +- `EVM_PRIVATE_KEY` - Ethereum private key (hex with 0x prefix) +- `SVM_PRIVATE_KEY` - Solana private key (base58 encoded) + +## Output Format + +```json +{ + "success": true, + "data": { "message": "Protected endpoint accessed" }, + "status_code": 200, + "payment_response": { + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x..." + } +} +``` + +## Package Dependencies + +- `@x402/fetch` - HTTP wrapper with payment handling +- `@x402/core` - Core x402 client and types +- `@x402/evm` - EVM payment mechanisms (V2) +- `@x402/evm/v1` - EVM payment mechanisms (V1) +- `@x402/svm` - SVM payment mechanisms (V2) +- `@x402/svm/v1` - SVM payment mechanisms (V1) +- `viem` - Ethereum library for account creation +- `@solana/kit` - Solana keypair utilities diff --git a/e2e/clients/axios/build.sh b/e2e/clients/axios/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/clients/axios/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/clients/axios/index.ts b/e2e/clients/axios/index.ts index c0b17553b..4d3bf4e0e 100644 --- a/e2e/clients/axios/index.ts +++ b/e2e/clients/axios/index.ts @@ -1,58 +1,68 @@ -import axios from "axios"; import { config } from "dotenv"; -import { Hex } from "viem"; -import { withPaymentInterceptor, decodeXPaymentResponse, createSigner, MultiNetworkSigner } from "x402-axios"; +import axios from "axios"; +import { wrapAxiosWithPayment, decodePaymentResponseHeader } from "@x402/axios"; +import { privateKeyToAccount } from "viem/accounts"; +import { registerExactEvmScheme } from "@x402/evm/exact/client"; +import { registerExactSvmScheme } from "@x402/svm/exact/client"; +import { base58 } from "@scure/base"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { x402Client } from "@x402/core/client"; config(); -const evmPrivateKey = process.env.EVM_PRIVATE_KEY as Hex; -const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string; -const baseURL = process.env.RESOURCE_SERVER_URL as string; // e.g. https://example.com -const endpointPath = process.env.ENDPOINT_PATH as string; // e.g. /weather - -if (!baseURL || !evmPrivateKey || !svmPrivateKey || !endpointPath) { - console.error("Missing required environment variables"); - process.exit(1); -} - -const evmSigner = await createSigner("base-sepolia", evmPrivateKey); -const svmSigner = await createSigner("solana-devnet", svmPrivateKey); -const account = { evm: evmSigner, svm: svmSigner } as MultiNetworkSigner; - -const api = withPaymentInterceptor( - axios.create({ - baseURL, - }), - account, +const baseURL = process.env.RESOURCE_SERVER_URL as string; +const endpointPath = process.env.ENDPOINT_PATH as string; +const url = `${baseURL}${endpointPath}`; +const evmAccount = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); +const svmSigner = await createKeyPairSignerFromBytes( + base58.decode(process.env.SVM_PRIVATE_KEY as string), ); -api - .get(endpointPath) - .then(response => { - console.log("Response received:", { - status: response.status, - headers: response.headers, - data: response.data - }); +// Create client and register EVM and SVM schemes using the new register helpers +const client = new x402Client(); +registerExactEvmScheme(client, { signer: evmAccount }); +registerExactSvmScheme(client, { signer: svmSigner }); + +const axiosWithPayment = wrapAxiosWithPayment(axios.create(), client); + +axiosWithPayment + .get(url) + .then(async (response) => { + const data = response.data; + // Check both v2 (PAYMENT-RESPONSE) and v1 (X-PAYMENT-RESPONSE) headers + const paymentResponse = + response.headers["payment-response"] || response.headers["x-payment-response"]; + + if (!paymentResponse) { + // No payment was required + const result = { + success: true, + data: data, + status_code: response.status, + }; + console.log(JSON.stringify(result)); + process.exit(0); + return; + } + + const decodedPaymentResponse = decodePaymentResponseHeader(paymentResponse); const result = { - success: true, - data: response.data, + success: decodedPaymentResponse.success, + data: data, status_code: response.status, - payment_response: decodeXPaymentResponse(response.headers["x-payment-response"]) + payment_response: decodedPaymentResponse, }; // Output structured result as JSON for proxy to parse console.log(JSON.stringify(result)); process.exit(0); }) - .catch(error => { - const errorResult = { + .catch((error) => { + console.error(JSON.stringify({ success: false, - error: error.message || String(error), - status_code: error.response?.status - }; - - console.log(JSON.stringify(errorResult)); + error: error.message || "Request failed", + status_code: error.response?.status || 500, + })); process.exit(1); }); diff --git a/e2e/clients/axios/install.sh b/e2e/clients/axios/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/clients/axios/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/clients/axios/package.json b/e2e/clients/axios/package.json index 0d50932e7..ad642a655 100644 --- a/e2e/clients/axios/package.json +++ b/e2e/clients/axios/package.json @@ -1,5 +1,5 @@ { - "name": "axios-e2e", + "name": "@x402/axios-e2e", "private": true, "type": "module", "scripts": { @@ -10,10 +10,15 @@ "lint:check": "eslint . --ext .ts" }, "dependencies": { + "@scure/base": "^1.2.6", + "@solana/kit": "^2.1.1", + "@x402/axios": "workspace:*", + "@x402/core": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/svm": "workspace:*", "axios": "^1.7.9", - "dotenv": "^16.5.0", - "viem": "^2.21.26", - "x402-axios": "workspace:*" + "dotenv": "^16.4.7", + "viem": "^2.21.26" }, "devDependencies": { "@eslint/js": "^9.24.0", diff --git a/e2e/clients/axios/test.config.json b/e2e/clients/axios/test.config.json index c94ad046b..4586c8306 100644 --- a/e2e/clients/axios/test.config.json +++ b/e2e/clients/axios/test.config.json @@ -6,6 +6,10 @@ "evm", "svm" ], + "x402Versions": [ + 1, + 2 + ], "environment": { "required": [ "EVM_PRIVATE_KEY", diff --git a/e2e/clients/axios/tsconfig.json b/e2e/clients/axios/tsconfig.json index 81e0e7f1f..1bdf94ca8 100644 --- a/e2e/clients/axios/tsconfig.json +++ b/e2e/clients/axios/tsconfig.json @@ -9,11 +9,7 @@ "strict": true, "resolveJsonModule": true, "baseUrl": ".", - "types": [ - "node" - ] + "types": ["node"] }, - "include": [ - "index.ts" - ] -} \ No newline at end of file + "include": ["index.ts"] +} diff --git a/e2e/clients/fetch/README.md b/e2e/clients/fetch/README.md index f04ed5516..463fb72b1 100644 --- a/e2e/clients/fetch/README.md +++ b/e2e/clients/fetch/README.md @@ -1,75 +1,118 @@ -# x402-fetch Example Client +# E2E Test Client: TypeScript Fetch -This is an example client that demonstrates how to use the `x402-fetch` package to make HTTP requests to endpoints protected by the x402 payment protocol. +This client demonstrates and tests the `@x402/fetch` package with both EVM and SVM payment support. -## Prerequisites +## What It Tests -- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) -- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) -- A running x402 server (you can use the example express server at `examples/typescript/servers/express`) -- A valid Ethereum private key for making payments +### Core Functionality +- ✅ **V2 Protocol** - Modern x402 protocol with CAIP-2 networks +- ✅ **V1 Protocol** - Legacy x402 protocol with simple network names +- ✅ **Multi-chain Support** - Both EVM and SVM in a single client +- ✅ **Automatic Payment Handling** - Transparent 402 response handling +- ✅ **Payment Response Decoding** - Extracts settlement information from headers -## Setup +### Payment Mechanisms +- ✅ **EVM V2** - `eip155:*` wildcard scheme +- ✅ **EVM V1** - `base-sepolia` and `base` networks +- ✅ **SVM V2** - `solana:*` wildcard scheme +- ✅ **SVM V1** - `solana-devnet` and `solana` networks -1. Install and build all packages from the typescript examples root: -```bash -cd ../../ -pnpm install -pnpm build -cd clients/fetch -``` +## What It Demonstrates -2. Copy `.env-local` to `.env` and add your Ethereum private key: -```bash -cp .env-local .env -``` +### Usage Pattern -3. Start the example client: -```bash -pnpm dev +```typescript +import { wrapFetchWithPayment } from "@x402/fetch"; +import { x402Client } from "@x402/core/client"; +import { ExactEvmClient } from "@x402/evm"; +import { ExactEvmClientV1 } from "@x402/evm/v1"; +import { ExactSvmClient } from "@x402/svm"; +import { ExactSvmClientV1 } from "@x402/svm/v1"; + +// Build x402 client with direct registration +const client = new x402Client() + .register("eip155:*", new ExactEvmClient(evmAccount)) + .register("solana:*", new ExactSvmClient(svmSigner)) + .registerV1("base-sepolia", new ExactEvmClientV1(evmAccount)) + .registerV1("base", new ExactEvmClientV1(evmAccount)) + .registerV1("solana-devnet", new ExactSvmClientV1(svmSigner)) + .registerV1("solana", new ExactSvmClientV1(svmSigner)); + +// Wrap fetch with payment handling +const fetchWithPayment = wrapFetchWithPayment(fetch, client); + +// Make request - 402 responses handled automatically +const response = await fetchWithPayment(url, { method: "GET" }); ``` -## How It Works +### Key Concepts Shown -The example demonstrates how to: -1. Create a wallet client using viem -2. Wrap the native fetch function with x402 payment handling -3. Make a request to a paid endpoint -4. Handle the response or any errors +1. **Builder Pattern** - Fluent API for registering multiple schemes +2. **Multi-Version Support** - V1 and V2 protocols side-by-side +3. **Multi-Chain Support** - EVM and SVM in one client +4. **Network Flexibility** - Wildcards for V2, specific networks for V1 +5. **Transparent Payment** - No manual 402 handling needed -## Example Code +## Test Scenarios -```typescript -import { config } from "dotenv"; -import { createWalletClient, http } from "viem"; -import { privateKeyToAccount } from "viem/accounts"; -import { wrapFetchWithPayment } from "x402-fetch"; -import { baseSepolia } from "viem/chains"; +This client is tested against: +- **Servers:** Express (TypeScript), Gin (Go) +- **Facilitators:** TypeScript, Go +- **Endpoints:** `/protected` (EVM), `/protected-svm` (SVM) +- **Networks:** Base Sepolia (EVM), Solana Devnet (SVM) -config(); +### Success Criteria +- ✅ Request succeeds with 200 status +- ✅ Payment response header present +- ✅ Transaction hash returned +- ✅ Payment marked as successful -const { RESOURCE_SERVER_URL, PRIVATE_KEY, ENDPOINT_PATH } = process.env; +## Running -// Create wallet client -const account = privateKeyToAccount(PRIVATE_KEY as `0x${string}`); -const client = createWalletClient({ - account, - transport: http(), - chain: baseSepolia, -}); +```bash +# Via e2e test suite +cd e2e +pnpm test --client=fetch + +# Direct execution (requires environment variables) +cd e2e/clients/fetch +export RESOURCE_SERVER_URL="http://localhost:4022" +export ENDPOINT_PATH="/protected" +export EVM_PRIVATE_KEY="0x..." +export SVM_PRIVATE_KEY="..." +pnpm start +``` -// Wrap fetch with payment handling -const fetchWithPay = wrapFetchWithPayment(fetch, client); - -// Make request to paid endpoint -fetchWithPay(`${RESOURCE_SERVER_URL}${ENDPOINT_PATH}`, { - method: "GET", -}) - .then(async response => { - const body = await response.json(); - console.log(body); - }) - .catch(error => { - console.error(error.response?.data?.error); - }); +## Environment Variables + +- `RESOURCE_SERVER_URL` - Server base URL +- `ENDPOINT_PATH` - Path to protected endpoint +- `EVM_PRIVATE_KEY` - Ethereum private key (hex with 0x prefix) +- `SVM_PRIVATE_KEY` - Solana private key (base58 encoded) + +## Output Format + +```json +{ + "success": true, + "data": { "message": "Protected endpoint accessed" }, + "status_code": 200, + "payment_response": { + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x..." + } +} ``` + +## Package Dependencies + +- `@x402/fetch` - HTTP wrapper with payment handling +- `@x402/core` - Core x402 client and types +- `@x402/evm` - EVM payment mechanisms (V2) +- `@x402/evm/v1` - EVM payment mechanisms (V1) +- `@x402/svm` - SVM payment mechanisms (V2) +- `@x402/svm/v1` - SVM payment mechanisms (V1) +- `viem` - Ethereum library for account creation +- `@solana/kit` - Solana keypair utilities diff --git a/e2e/clients/fetch/build.sh b/e2e/clients/fetch/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/clients/fetch/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/clients/fetch/index.ts b/e2e/clients/fetch/index.ts index e7625705a..2ff4121ef 100644 --- a/e2e/clients/fetch/index.ts +++ b/e2e/clients/fetch/index.ts @@ -1,51 +1,53 @@ import { config } from "dotenv"; -import { Hex } from "viem"; -import { createSigner, decodeXPaymentResponse, MultiNetworkSigner, wrapFetchWithPayment } from "x402-fetch"; +import { wrapFetchWithPayment, decodePaymentResponseHeader } from "@x402/fetch"; +import { privateKeyToAccount } from "viem/accounts"; +import { registerExactEvmScheme } from "@x402/evm/exact/client"; +import { registerExactSvmScheme } from "@x402/svm/exact/client"; +import { base58 } from "@scure/base"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { x402Client, x402HTTPClient } from "@x402/core/client"; config(); -const evmPrivateKey = process.env.EVM_PRIVATE_KEY as Hex; -const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string; const baseURL = process.env.RESOURCE_SERVER_URL as string; const endpointPath = process.env.ENDPOINT_PATH as string; const url = `${baseURL}${endpointPath}`; +const evmAccount = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); +const svmSigner = await createKeyPairSignerFromBytes(base58.decode(process.env.SVM_PRIVATE_KEY as string)); -if (!baseURL || !evmPrivateKey || !svmPrivateKey || !endpointPath) { - console.error("Missing required environment variables"); - process.exit(1); -} +// Create client and register EVM and SVM schemes using the new register helpers +const client = new x402Client(); +registerExactEvmScheme(client, { signer: evmAccount }); +registerExactSvmScheme(client, { signer: svmSigner }); -const evmSigner = await createSigner("base-sepolia", evmPrivateKey); -const svmSigner = await createSigner("solana-devnet", svmPrivateKey); -const account = { evm: evmSigner, svm: svmSigner } as MultiNetworkSigner; - -const fetchWithPayment = wrapFetchWithPayment(fetch, account); +const fetchWithPayment = wrapFetchWithPayment(fetch, client); fetchWithPayment(url, { method: "GET", -}) - .then(async response => { - const data = await response.json(); - const paymentResponse = response.headers.get("x-payment-response"); +}).then(async response => { + const data = await response.json(); + const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse((name) => response.headers.get(name)); + if (!paymentResponse) { + // No payment was required const result = { success: true, data: data, status_code: response.status, - payment_response: decodeXPaymentResponse(paymentResponse!) }; - - // Output structured result as JSON for proxy to parse console.log(JSON.stringify(result)); process.exit(0); - }) - .catch(error => { - const errorResult = { - success: false, - error: error.message || String(error), - status_code: error.response?.status - }; - - console.log(JSON.stringify(errorResult)); - process.exit(1); - }); + return; + } + + const result = { + success: paymentResponse.success, + data: data, + status_code: response.status, + payment_response: paymentResponse, + }; + + // Output structured result as JSON for proxy to parse + console.log(JSON.stringify(result)); + process.exit(0); +}); diff --git a/e2e/clients/fetch/install.sh b/e2e/clients/fetch/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/clients/fetch/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/clients/fetch/package.json b/e2e/clients/fetch/package.json index f079ea58f..31f478ba7 100644 --- a/e2e/clients/fetch/package.json +++ b/e2e/clients/fetch/package.json @@ -1,5 +1,5 @@ { - "name": "fetch-client-example", + "name": "@x402/fetch-e2e", "private": true, "type": "module", "scripts": { @@ -10,21 +10,26 @@ "lint:check": "eslint . --ext .ts" }, "dependencies": { + "@scure/base": "^1.2.6", + "@solana/kit": "^2.1.1", + "@x402/core": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/fetch": "workspace:*", + "@x402/svm": "workspace:*", "axios": "^1.7.9", "dotenv": "^16.4.7", - "viem": "^2.21.26", - "x402-fetch": "workspace:*" + "viem": "^2.21.26" }, "devDependencies": { "@eslint/js": "^9.24.0", - "eslint": "^9.24.0", - "eslint-plugin-jsdoc": "^50.6.9", - "eslint-plugin-prettier": "^5.2.6", "@typescript-eslint/eslint-plugin": "^8.29.1", "@typescript-eslint/parser": "^8.29.1", + "eslint": "^9.24.0", "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", "prettier": "3.5.2", "tsx": "^4.7.0", "typescript": "^5.3.0" } -} +} \ No newline at end of file diff --git a/e2e/clients/fetch/test.config.json b/e2e/clients/fetch/test.config.json index f738ce6da..6d20d8b16 100644 --- a/e2e/clients/fetch/test.config.json +++ b/e2e/clients/fetch/test.config.json @@ -6,6 +6,10 @@ "evm", "svm" ], + "x402Versions": [ + 1, + 2 + ], "environment": { "required": [ "EVM_PRIVATE_KEY", diff --git a/e2e/clients/fetch/tsconfig.json b/e2e/clients/fetch/tsconfig.json index 81e0e7f1f..1bdf94ca8 100644 --- a/e2e/clients/fetch/tsconfig.json +++ b/e2e/clients/fetch/tsconfig.json @@ -9,11 +9,7 @@ "strict": true, "resolveJsonModule": true, "baseUrl": ".", - "types": [ - "node" - ] + "types": ["node"] }, - "include": [ - "index.ts" - ] -} \ No newline at end of file + "include": ["index.ts"] +} diff --git a/e2e/clients/go-http/README.md b/e2e/clients/go-http/README.md new file mode 100644 index 000000000..9d4d019f2 --- /dev/null +++ b/e2e/clients/go-http/README.md @@ -0,0 +1,143 @@ +# E2E Test Client: Go HTTP + +This client demonstrates and tests the Go x402 HTTP client with both EVM and SVM payment support. + +## What It Tests + +### Core Functionality +- ✅ **V2 Protocol** - Modern x402 protocol with CAIP-2 networks +- ✅ **V1 Protocol** - Legacy x402 protocol with simple network names +- ✅ **Multi-chain Support** - Both EVM and SVM in a single client +- ✅ **HTTP RoundTripper Integration** - Transparent payment via Go's http.Client +- ✅ **Automatic Retry** - Handles 402 responses and retries with payment +- ✅ **Payment Response Extraction** - Decodes settlement info from headers + +### Payment Mechanisms +- ✅ **EVM V2** - `eip155:*` wildcard scheme +- ✅ **EVM V1** - `base-sepolia` and `base` networks +- ✅ **SVM V2** - `solana:*` wildcard scheme +- ✅ **SVM V1** - `solana-devnet` and `solana` networks + +## What It Demonstrates + +### Usage Pattern + +```go +import ( + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + "github.com/coinbase/x402/go/mechanisms/evm" + evmv1 "github.com/coinbase/x402/go/mechanisms/evm/exact/v1" + "github.com/coinbase/x402/go/mechanisms/svm" + svmv1 "github.com/coinbase/x402/go/mechanisms/svm/exact/v1" +) + +// Create x402 client with direct registration +x402Client := x402.Newx402Client() + +// Register EVM support +x402Client.Register("eip155:*", evm.NewExactEvmClient(evmSigner)) +x402Client.RegisterV1("base-sepolia", evmv1.NewExactEvmClientV1(evmSigner)) + +// Register SVM support +x402Client.Register("solana:*", svm.NewExactSvmClient(svmSigner)) +x402Client.RegisterV1("solana-devnet", svmv1.NewExactSvmClientV1(svmSigner)) + +// Create HTTP wrapper +httpClient := x402http.Newx402HTTPClient(x402Client) + +// Wrap standard http.Client +client := x402http.WrapHTTPClientWithPayment(http.DefaultClient, httpClient) + +// Make request - 402 responses handled automatically +resp, err := client.Get(url) +``` + +### Key Concepts Shown + +1. **Builder Pattern** - Fluent API for registering multiple schemes +2. **Multi-Version Support** - V1 and V2 protocols coexist +3. **Multi-Chain Support** - EVM and SVM in one client +4. **HTTP Integration** - Wraps standard Go http.Client +5. **No Config Required** - SVM clients use network defaults +6. **Automatic Signing** - Real EIP-712 and Solana Ed25519 signatures + +## Test Scenarios + +This client is tested against: +- **Servers:** Express (TypeScript), Gin (Go) +- **Facilitators:** TypeScript, Go +- **Endpoints:** `/protected` (EVM), `/protected-svm` (SVM) +- **Networks:** Base Sepolia (EVM), Solana Devnet (SVM) + +### Success Criteria +- ✅ Request succeeds with 200 status +- ✅ Payment response header present +- ✅ Transaction hash returned +- ✅ Payment marked as successful + +## Running + +```bash +# Via e2e test suite +cd e2e +pnpm test --client=go-http + +# Direct execution (requires environment variables) +cd e2e/clients/go-http +export RESOURCE_SERVER_URL="http://localhost:4022" +export ENDPOINT_PATH="/protected" +export EVM_PRIVATE_KEY="0x..." +export SVM_PRIVATE_KEY="..." +./go-http +``` + +## Environment Variables + +- `RESOURCE_SERVER_URL` - Server base URL +- `ENDPOINT_PATH` - Path to protected endpoint +- `EVM_PRIVATE_KEY` - Ethereum private key (hex with 0x prefix) +- `SVM_PRIVATE_KEY` - Solana private key (base58 encoded) + +## Output Format + +```json +{ + "success": true, + "data": { "message": "Protected endpoint accessed" }, + "status_code": 200, + "payment_response": { + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x..." + } +} +``` + +## Implementation Details + +### EVM Signer +- Derives address from private key +- Implements EIP-712 typed data signing +- Uses go-ethereum's crypto package +- Generates valid Ethereum signatures with recovery ID + +### SVM Signer +- Uses ed25519 keypair +- Signs Solana transactions +- Partial signing (client signs, facilitator completes) + +### RPC Resolution +- **Automatic** - SVM clients resolve RPC URLs from network config +- **No manual config needed** - Defaults to public Solana RPCs +- **Customizable** - Can override with `ClientConfig` if needed + +## Dependencies + +- `github.com/coinbase/x402/go` - Core x402 protocol +- `github.com/coinbase/x402/go/http` - HTTP integration +- `github.com/coinbase/x402/go/mechanisms/evm` - EVM mechanisms +- `github.com/coinbase/x402/go/mechanisms/svm` - SVM mechanisms +- `github.com/ethereum/go-ethereum` - Ethereum Go library +- `github.com/gagliardetto/solana-go` - Solana Go library diff --git a/e2e/clients/go-http/build.sh b/e2e/clients/go-http/build.sh new file mode 100755 index 000000000..ae70f56e9 --- /dev/null +++ b/e2e/clients/go-http/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Building go-http client..." +go build -o main . +echo "✅ Build completed: main" + diff --git a/e2e/clients/go-http/client b/e2e/clients/go-http/client new file mode 100755 index 000000000..35cfd3ada Binary files /dev/null and b/e2e/clients/go-http/client differ diff --git a/e2e/clients/go-http/go-http b/e2e/clients/go-http/go-http new file mode 100755 index 000000000..1a08eb43d Binary files /dev/null and b/e2e/clients/go-http/go-http differ diff --git a/e2e/clients/go-http/go.mod b/e2e/clients/go-http/go.mod new file mode 100644 index 000000000..4538d80df --- /dev/null +++ b/e2e/clients/go-http/go.mod @@ -0,0 +1,54 @@ +module github.com/coinbase/x402-go/e2e/clients/go-http + +go 1.24.0 + +toolchain go1.24.1 + +require github.com/coinbase/x402/go v0.0.0 + +require ( + filippo.io/edwards25519 v1.0.0-rc.1 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/blendle/zapdriver v1.3.1 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/gagliardetto/binary v0.8.0 // indirect + github.com/gagliardetto/solana-go v1.14.0 // indirect + github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + go.mongodb.org/mongo-driver v1.12.2 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/ratelimit v0.2.0 // indirect + go.uber.org/zap v1.21.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/time v0.9.0 // indirect +) + +replace github.com/coinbase/x402/go => ../../../go diff --git a/e2e/clients/go-http/go.sum b/e2e/clients/go-http/go.sum new file mode 100644 index 000000000..2f09f58e9 --- /dev/null +++ b/e2e/clients/go-http/go.sum @@ -0,0 +1,231 @@ +filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= +github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= +github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= +github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= +github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= +github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/crate-crypto/go-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg= +github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= +github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s= +github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs= +github.com/ethereum/go-ethereum v1.16.7 h1:qeM4TvbrWK0UC0tgkZ7NiRsmBGwsjqc64BHo20U59UQ= +github.com/ethereum/go-ethereum v1.16.7/go.mod h1:Fs6QebQbavneQTYcA39PEKv2+zIjX7rPUZ14DER46wk= +github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= +github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= +github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= +github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= +github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= +github.com/gagliardetto/solana-go v1.14.0 h1:3WfAi70jOOjAJ0deFMjdhFYlLXATF4tOQXsDNWJtOLw= +github.com/gagliardetto/solana-go v1.14.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= +github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= +github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.12.2 h1:gbWY1bJkkmUB9jjZzcdhOL8O85N9H+Vvsf2yFN0RDws= +go.mongodb.org/mongo-driver v1.12.2/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA= +go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/e2e/clients/go-http/install.sh b/e2e/clients/go-http/install.sh new file mode 100755 index 000000000..e7db1210b --- /dev/null +++ b/e2e/clients/go-http/install.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Installing Go dependencies for go-http client..." +go mod tidy +echo "✅ Dependencies installed" + diff --git a/e2e/clients/go-http/main b/e2e/clients/go-http/main new file mode 100755 index 000000000..cdf89d869 Binary files /dev/null and b/e2e/clients/go-http/main differ diff --git a/e2e/clients/go-http/main.go b/e2e/clients/go-http/main.go new file mode 100644 index 000000000..6ad762bb8 --- /dev/null +++ b/e2e/clients/go-http/main.go @@ -0,0 +1,160 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "net/http" + "os" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmv1 "github.com/coinbase/x402/go/mechanisms/evm/exact/v1/client" + svm "github.com/coinbase/x402/go/mechanisms/svm/exact/client" + svmv1 "github.com/coinbase/x402/go/mechanisms/svm/exact/v1/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" + svmsigners "github.com/coinbase/x402/go/signers/svm" +) + +// Result structure for e2e test output +type Result struct { + Success bool `json:"success"` + Data interface{} `json:"data,omitempty"` + StatusCode int `json:"status_code,omitempty"` + PaymentResponse interface{} `json:"payment_response,omitempty"` + Error string `json:"error,omitempty"` +} + +func main() { + // Get configuration from environment + serverURL := os.Getenv("RESOURCE_SERVER_URL") + if serverURL == "" { + log.Fatal("RESOURCE_SERVER_URL is required") + } + + endpointPath := os.Getenv("ENDPOINT_PATH") + if endpointPath == "" { + endpointPath = "/protected" + } + + evmPrivateKey := os.Getenv("EVM_PRIVATE_KEY") + if evmPrivateKey == "" { + log.Fatal("❌ EVM_PRIVATE_KEY environment variable is required") + } + + svmPrivateKey := os.Getenv("SVM_PRIVATE_KEY") + if svmPrivateKey == "" { + log.Fatal("❌ SVM_PRIVATE_KEY environment variable is required") + } + + evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(evmPrivateKey) + if err != nil { + outputError(fmt.Sprintf("Failed to create EVM signer: %v", err)) + return + } + + svmSigner, err := svmsigners.NewClientSignerFromPrivateKey(svmPrivateKey) + if err != nil { + outputError(fmt.Sprintf("Failed to create SVM signer: %v", err)) + return + } + + // Create x402 client with fluent API + x402Client := x402.Newx402Client(). + Register("eip155:*", evm.NewExactEvmScheme(evmSigner)). + Register("solana:*", svm.NewExactSvmScheme(svmSigner)). + RegisterV1("base-sepolia", evmv1.NewExactEvmSchemeV1(evmSigner)). + RegisterV1("base", evmv1.NewExactEvmSchemeV1(evmSigner)). + RegisterV1("solana-devnet", svmv1.NewExactSvmSchemeV1(svmSigner)). + RegisterV1("solana", svmv1.NewExactSvmSchemeV1(svmSigner)) + + // Create HTTP client wrapper + httpClient := x402http.Newx402HTTPClient(x402Client) + + // Wrap standard HTTP client with payment handling + client := x402http.WrapHTTPClientWithPayment(http.DefaultClient, httpClient) + + // Make the request + url := serverURL + endpointPath + ctx := context.Background() + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + outputError(fmt.Sprintf("Failed to create request: %v", err)) + return + } + + // Perform the request (payment will be handled) + resp, err := client.Do(req) + if err != nil { + outputError(fmt.Sprintf("Request failed: %v", err)) + return + } + defer resp.Body.Close() + + // Read response body + var responseData interface{} + if err := json.NewDecoder(resp.Body).Decode(&responseData); err != nil { + outputError(fmt.Sprintf("Failed to decode response: %v", err)) + return + } + + // Extract payment response from headers if present + var paymentResponse interface{} + if paymentHeader := resp.Header.Get("PAYMENT-RESPONSE"); paymentHeader != "" { + settleResp, err := httpClient.GetPaymentSettleResponse(map[string]string{ + "PAYMENT-RESPONSE": paymentHeader, + }) + if err == nil { + paymentResponse = settleResp + } + } else if paymentHeader := resp.Header.Get("X-PAYMENT-RESPONSE"); paymentHeader != "" { + settleResp, err := httpClient.GetPaymentSettleResponse(map[string]string{ + "X-PAYMENT-RESPONSE": paymentHeader, + }) + if err == nil { + paymentResponse = settleResp + } + } + + // Check if payment was successful (if a payment was required) + success := true + if resp.StatusCode == 402 { + // Payment was required but we got a 402, so payment failed + success = false + } else if settleResp, ok := paymentResponse.(*x402.SettleResponse); ok && paymentResponse != nil { + // Payment was attempted, check if it succeeded + success = settleResp.Success + } + + // Output result + result := Result{ + Success: success, + Data: responseData, + StatusCode: resp.StatusCode, + PaymentResponse: paymentResponse, + } + + outputResult(result) +} + +func outputResult(result Result) { + data, err := json.Marshal(result) + if err != nil { + log.Fatalf("Failed to marshal result: %v", err) + } + fmt.Println(string(data)) + os.Exit(0) +} + +func outputError(errorMsg string) { + result := Result{ + Success: false, + Error: errorMsg, + } + data, _ := json.Marshal(result) + fmt.Println(string(data)) + os.Exit(1) +} diff --git a/e2e/clients/go-http/run.sh b/e2e/clients/go-http/run.sh new file mode 100755 index 000000000..5f2f5f850 --- /dev/null +++ b/e2e/clients/go-http/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +go run main.go diff --git a/e2e/clients/go-http/test.config.json b/e2e/clients/go-http/test.config.json new file mode 100644 index 000000000..f15910128 --- /dev/null +++ b/e2e/clients/go-http/test.config.json @@ -0,0 +1,22 @@ +{ + "name": "go-http", + "type": "client", + "language": "go", + "protocolFamilies": [ + "evm", + "svm" + ], + "x402Versions": [ + 1, + 2 + ], + "environment": { + "required": [ + "EVM_PRIVATE_KEY", + "SVM_PRIVATE_KEY", + "RESOURCE_SERVER_URL", + "ENDPOINT_PATH" + ], + "optional": [] + } +} \ No newline at end of file diff --git a/e2e/clients/text-client-protocol.txt b/e2e/clients/text-client-protocol.txt index f1ae00841..ad2e5ce22 100644 --- a/e2e/clients/text-client-protocol.txt +++ b/e2e/clients/text-client-protocol.txt @@ -11,6 +11,10 @@ Clients must declare which protocol families they support in their test.config.j - **EVM**: Ethereum Virtual Machine compatible networks (Base, Ethereum, etc.) - **SVM**: Solana Virtual Machine compatible networks (Solana, etc.) +## X402 Version Support +Clients must declare which x402 protocol versions they support using the `x402Versions` field: +- **x402Versions**: Array of supported x402 protocol versions (e.g., [1, 2]) + Example configuration: ```json { @@ -18,6 +22,7 @@ Example configuration: "type": "client", "language": "typescript", "protocolFamilies": ["evm"], + "x402Versions": [1, 2], "environment": { "required": ["EVM_PRIVATE_KEY", "RESOURCE_SERVER_URL", "ENDPOINT_PATH"], "optional": [] @@ -32,6 +37,7 @@ Multi-protocol client example: "type": "client", "language": "typescript", "protocolFamilies": ["evm", "svm"], + "x402Versions": [1, 2], "environment": { "required": ["EVM_PRIVATE_KEY", "SVM_PRIVATE_KEY", "RESOURCE_SERVER_URL", "ENDPOINT_PATH"], "optional": [] diff --git a/e2e/extensions/bazaar.ts b/e2e/extensions/bazaar.ts new file mode 100644 index 000000000..4f585985e --- /dev/null +++ b/e2e/extensions/bazaar.ts @@ -0,0 +1,404 @@ +/** + * Bazaar Discovery Extension Validation for E2E Tests + * + * This module validates that the bazaar discovery extension is working correctly + * by checking that facilitators have discovered all expected endpoints from servers. + */ + +import { log, verboseLog, errorLog } from '../src/logger'; +import type { FacilitatorProxy, DiscoveredServer, TestConfig } from '../src/types'; + +/** + * Discovery resources response structure + */ +interface DiscoveryResourcesResponse { + x402Version: number; + items: Array<{ + resource: string; + type: string; + x402Version: number; + accepts: any[]; + discoveryInfo?: any; + lastUpdated: string; + metadata?: Record; + }>; + pagination: { + limit: number; + offset: number; + total: number; + }; +} + +/** + * Expected endpoint that should be discovered + */ +interface ExpectedDiscoverableEndpoint { + serverName: string; + serverUrl: string; + endpointPath: string; + method: string; + description: string; +} + +/** + * Validation result for a single facilitator + */ +interface FacilitatorDiscoveryResult { + facilitatorName: string; + facilitatorUrl: string; + totalDiscovered: number; + expectedEndpoints: ExpectedDiscoverableEndpoint[]; + discoveredEndpoints: string[]; + missingEndpoints: ExpectedDiscoverableEndpoint[]; + unexpectedEndpoints: string[]; + success: boolean; + error?: string; +} + +/** + * Overall discovery validation result + */ +export interface DiscoveryValidationResult { + totalFacilitators: number; + facilitatorsChecked: number; + facilitatorResults: FacilitatorDiscoveryResult[]; + totalExpectedEndpoints: number; + totalDiscoveredEndpoints: number; + allEndpointsDiscovered: boolean; + success: boolean; +} + +/** + * Check if a server supports the bazaar extension + */ +function serverSupportsBazaar(serverConfig: TestConfig): boolean { + return serverConfig.extensions?.includes('bazaar') ?? false; +} + +/** + * Check if a facilitator supports the bazaar extension + */ +function facilitatorSupportsBazaar(facilitatorConfig: TestConfig): boolean { + return facilitatorConfig.extensions?.includes('bazaar') ?? false; +} + +/** + * Get discoverable endpoints from a server config + */ +function getDiscoverableEndpoints( + server: DiscoveredServer, + serverPort: number +): ExpectedDiscoverableEndpoint[] { + if (!serverSupportsBazaar(server.config)) { + return []; + } + + const serverUrl = `http://localhost:${serverPort}`; + const discoverableEndpoints: ExpectedDiscoverableEndpoint[] = []; + + // Find all payment-required endpoints (these should have discovery info) + const paymentEndpoints = server.config.endpoints?.filter( + endpoint => endpoint.requiresPayment === true + ) || []; + + for (const endpoint of paymentEndpoints) { + discoverableEndpoints.push({ + serverName: server.config.name, + serverUrl, + endpointPath: endpoint.path, + method: endpoint.method, + description: endpoint.description, + }); + } + + return discoverableEndpoints; +} + +/** + * Fetch discovered resources from a facilitator + */ +async function fetchDiscoveredResources( + facilitatorProxy: FacilitatorProxy +): Promise { + try { + const url = `${facilitatorProxy.getUrl()}/discovery/resources?limit=1000`; + verboseLog(` 📡 Fetching discovered resources from: ${url}`); + + const response = await fetch(url); + + if (!response.ok) { + errorLog(` ❌ Failed to fetch discovery resources: ${response.status} ${response.statusText}`); + return null; + } + + const data = await response.json(); + return data as DiscoveryResourcesResponse; + } catch (error) { + errorLog(` ❌ Error fetching discovery resources: ${error instanceof Error ? error.message : String(error)}`); + return null; + } +} + +/** + * Validate discovery for a single facilitator + */ +async function validateFacilitatorDiscovery( + facilitatorProxy: FacilitatorProxy, + facilitatorConfig: TestConfig, + expectedEndpoints: ExpectedDiscoverableEndpoint[] +): Promise { + const facilitatorName = facilitatorConfig.name; + const facilitatorUrl = facilitatorProxy.getUrl(); + + verboseLog(`\n 🔍 Validating discovery for facilitator: ${facilitatorName}`); + verboseLog(` 📍 URL: ${facilitatorUrl}`); + + // Check if facilitator supports bazaar + if (!facilitatorSupportsBazaar(facilitatorConfig)) { + verboseLog(` ⏭️ Facilitator does not support bazaar extension, skipping`); + return { + facilitatorName, + facilitatorUrl, + totalDiscovered: 0, + expectedEndpoints: [], + discoveredEndpoints: [], + missingEndpoints: [], + unexpectedEndpoints: [], + success: true, // Not a failure if facilitator doesn't support bazaar + }; + } + + // Fetch discovered resources + const discoveryResponse = await fetchDiscoveredResources(facilitatorProxy); + + if (!discoveryResponse) { + return { + facilitatorName, + facilitatorUrl, + totalDiscovered: 0, + expectedEndpoints, + discoveredEndpoints: [], + missingEndpoints: expectedEndpoints, + unexpectedEndpoints: [], + success: false, + error: 'Failed to fetch discovery resources', + }; + } + + verboseLog(` 📊 Total resources discovered: ${discoveryResponse.items.length}`); + + // Build set of discovered resource URLs for easy comparison + const discoveredUrls = new Set( + discoveryResponse.items.map(item => item.resource) + ); + + // Check which expected endpoints were discovered + const missingEndpoints: ExpectedDiscoverableEndpoint[] = []; + const discoveredEndpoints: string[] = []; + + for (const expected of expectedEndpoints) { + const expectedResourceUrl = `${expected.serverUrl}${expected.endpointPath}`; + + if (discoveredUrls.has(expectedResourceUrl)) { + discoveredEndpoints.push(expectedResourceUrl); + verboseLog(` ✅ Discovered: ${expected.method} ${expectedResourceUrl}`); + } else { + missingEndpoints.push(expected); + verboseLog(` ❌ Missing: ${expected.method} ${expectedResourceUrl}`); + } + } + + // Find any unexpected resources (discovered but not expected) + const expectedUrls = new Set( + expectedEndpoints.map(e => `${e.serverUrl}${e.endpointPath}`) + ); + const unexpectedEndpoints = discoveryResponse.items + .filter(item => !expectedUrls.has(item.resource)) + .map(item => item.resource); + + if (unexpectedEndpoints.length > 0) { + verboseLog(` ℹ️ Unexpected endpoints discovered: ${unexpectedEndpoints.length}`); + unexpectedEndpoints.forEach(url => verboseLog(` • ${url}`)); + } + + const success = missingEndpoints.length === 0; + + return { + facilitatorName, + facilitatorUrl, + totalDiscovered: discoveryResponse.items.length, + expectedEndpoints, + discoveredEndpoints, + missingEndpoints, + unexpectedEndpoints, + success, + }; +} + +/** + * Main discovery validation handler + * + * Validates that all expected endpoints have been discovered by facilitators + * + * @param facilitators - Array of facilitator proxies with their configs + * @param servers - Array of discovered servers with their configs + * @param serverPorts - Map of server name to port number + * @param facilitatorServerMap - Optional map tracking which facilitators processed which servers (for minimized test runs) + * @returns Validation result + * + * @example + * ```typescript + * const result = await handleDiscoveryValidation( + * facilitators.map(f => ({ proxy: f.proxy, config: f.config })), + * servers, + * new Map([['express', 4021], ['hono', 4022]]) + * ); + * + * if (!result.success) { + * console.error('Discovery validation failed'); + * } + * ``` + */ +export async function handleDiscoveryValidation( + facilitators: Array<{ proxy: FacilitatorProxy; config: TestConfig }>, + servers: DiscoveredServer[], + serverPorts: Map, + facilitatorServerMap?: Map> +): Promise { + log('\n╔════════════════════════════════════════════════════════╗'); + log('║ Bazaar Discovery Extension Validation ║'); + log('╚════════════════════════════════════════════════════════╝'); + + // Calculate all expected discoverable endpoints + const allExpectedEndpoints: ExpectedDiscoverableEndpoint[] = []; + + for (const server of servers) { + const serverPort = serverPorts.get(server.config.name); + if (!serverPort) { + verboseLog(` ⚠️ No port found for server: ${server.config.name}, skipping`); + continue; + } + + const serverEndpoints = getDiscoverableEndpoints(server, serverPort); + allExpectedEndpoints.push(...serverEndpoints); + } + + log(`\n📋 Expected Discoverable Endpoints: ${allExpectedEndpoints.length}`); + if (allExpectedEndpoints.length > 0) { + verboseLog(''); + allExpectedEndpoints.forEach(endpoint => { + verboseLog(` • ${endpoint.method} ${endpoint.serverUrl}${endpoint.endpointPath} (${endpoint.serverName})`); + }); + } + + // Validate each facilitator + const facilitatorResults: FacilitatorDiscoveryResult[] = []; + let facilitatorsChecked = 0; + let totalDiscovered = 0; + + for (const { proxy, config } of facilitators) { + // Filter expected endpoints to only those from servers this facilitator actually processed + let facilitatorExpectedEndpoints = allExpectedEndpoints; + + if (facilitatorServerMap) { + const processedServers = facilitatorServerMap.get(config.name); + if (processedServers && processedServers.size > 0) { + facilitatorExpectedEndpoints = allExpectedEndpoints.filter( + endpoint => processedServers.has(endpoint.serverName) + ); + + verboseLog(`\n 📋 Facilitator ${config.name} processed ${processedServers.size} server(s): ${Array.from(processedServers).join(', ')}`); + verboseLog(` Expected to discover ${facilitatorExpectedEndpoints.length} endpoint(s) from those servers`); + } + } + + const result = await validateFacilitatorDiscovery( + proxy, + config, + facilitatorExpectedEndpoints + ); + + facilitatorResults.push(result); + + if (facilitatorSupportsBazaar(config)) { + facilitatorsChecked++; + totalDiscovered += result.totalDiscovered; + } + } + + // Determine overall success + const allEndpointsDiscovered = facilitatorResults.every(r => r.success); + const hasExpectedEndpoints = allExpectedEndpoints.length > 0; + const success = !hasExpectedEndpoints || allEndpointsDiscovered; + + // Print summary + log('\n═══════════════════════════════════════════════════════'); + log(' Discovery Summary'); + log('═══════════════════════════════════════════════════════'); + log(`Total Facilitators: ${facilitators.length}`); + log(`Facilitators with Bazaar: ${facilitatorsChecked}`); + log(`Expected Endpoints: ${allExpectedEndpoints.length}`); + log(`Total Discovered Resources: ${totalDiscovered}`); + + // Print per-facilitator results + for (const result of facilitatorResults) { + if (!facilitatorSupportsBazaar(facilitators.find(f => f.config.name === result.facilitatorName)!.config)) { + continue; + } + + log(`\n📍 ${result.facilitatorName}:`); + log(` Discovered: ${result.discoveredEndpoints.length}/${result.expectedEndpoints.length}`); + + if (result.missingEndpoints.length > 0) { + errorLog(` ❌ Missing: ${result.missingEndpoints.length}`); + result.missingEndpoints.forEach(endpoint => { + errorLog(` • ${endpoint.method} ${endpoint.serverUrl}${endpoint.endpointPath}`); + }); + } else if (result.expectedEndpoints.length > 0) { + log(` ✅ All expected endpoints discovered`); + } + + if (result.unexpectedEndpoints.length > 0) { + verboseLog(` ℹ️ Unexpected: ${result.unexpectedEndpoints.length}`); + result.unexpectedEndpoints.forEach(url => { + verboseLog(` • ${url}`); + }); + } + + if (result.error) { + errorLog(` ❌ Error: ${result.error}`); + } + } + + log('\n═══════════════════════════════════════════════════════'); + if (success) { + log('✅ Discovery Validation: PASSED'); + } else { + errorLog('❌ Discovery Validation: FAILED'); + } + log('═══════════════════════════════════════════════════════\n'); + + return { + totalFacilitators: facilitators.length, + facilitatorsChecked, + facilitatorResults, + totalExpectedEndpoints: allExpectedEndpoints.length, + totalDiscoveredEndpoints: totalDiscovered, + allEndpointsDiscovered, + success, + }; +} + +/** + * Checks if any servers or facilitators support the bazaar extension + */ +export function shouldRunDiscoveryValidation( + facilitators: Array<{ config: TestConfig }>, + servers: DiscoveredServer[] +): boolean { + const hasServerWithBazaar = servers.some(s => serverSupportsBazaar(s.config)); + const hasFacilitatorWithBazaar = facilitators.some(f => facilitatorSupportsBazaar(f.config)); + + return hasServerWithBazaar && hasFacilitatorWithBazaar; +} + diff --git a/e2e/facilitators/external-proxies/README.md b/e2e/facilitators/external-proxies/README.md new file mode 100644 index 000000000..3b27102d2 --- /dev/null +++ b/e2e/facilitators/external-proxies/README.md @@ -0,0 +1,36 @@ +# External Facilitator Proxies + +This directory contains proxy facilitators that connect to **external production facilitators** for E2E testing. + +## Purpose + +External proxies allow testing against real-world facilitator implementations without including their implementation details in this repository. They act as bridges between the test suite and external services. + +## Structure + +- **`/external-proxies/`** - (gitignored) For local development facilitators or private testing + +## Local Development + +The `external-proxies/` directory is gitignored and meant for: +- Testing development facilitators locally +- Proxies you don't want to commit to the repository +- Personal facilitator configurations + +## Configuration + +Each proxy requires: +1. A `test.config.json` with facilitator metadata +2. Required environment variables (e.g., API keys) +3. Implementation that forwards requests to the external facilitator + +See individual proxy directories for specific setup requirements. + +## Selection Behavior + +External facilitators: +- Are **not selected by default** +- Display under an "External" grouping in interactive mode +- Require explicit selection by developers +- Must have all required environment variables set before running + diff --git a/e2e/facilitators/go/README.md b/e2e/facilitators/go/README.md new file mode 100644 index 000000000..40212e412 --- /dev/null +++ b/e2e/facilitators/go/README.md @@ -0,0 +1,266 @@ +# E2E Test Facilitator: Go + +This facilitator demonstrates and tests the Go x402 facilitator implementation with both EVM and SVM payment verification and settlement. + +## What It Demonstrates + +### Lifecycle Hooks Usage + +This e2e facilitator showcases **production-ready lifecycle hook patterns**: + +```go +facilitator := x402.Newx402Facilitator() + .Register("eip155:*", evmFacilitator) + .RegisterExtension(exttypes.BAZAAR) + // Hook 1: Track verified payments + extract discovery info + .OnAfterVerify(func(ctx x402.FacilitatorVerifyResultContext) error { + if ctx.Result.IsValid { + paymentHash := createPaymentHash(ctx.PaymentPayload) + verifiedPayments[paymentHash] = ctx.Timestamp.Unix() + + // Catalog discovered resources + discovered, _ := bazaar.ExtractDiscoveredResourceFromPaymentPayload(ctx.PayloadBytes, ctx.RequirementsBytes, true) + if discovered != nil { + bazaarCatalog.CatalogResource(discovered) + } + } + return nil + }). + // Hook 2: Validate payment was verified before settlement + OnBeforeSettle(func(ctx x402.FacilitatorSettleContext) (*x402.FacilitatorBeforeHookResult, error) { + paymentHash := createPaymentHash(ctx.PaymentPayload) + if !verifiedPayments.has(paymentHash) { + return &x402.FacilitatorBeforeHookResult{ + Abort: true, + Reason: "Payment must be verified first", + }, nil + } + + // Check timeout + age := ctx.Timestamp.Unix() - verifiedPayments[paymentHash] + if age > 5*60 { + return &x402.FacilitatorBeforeHookResult{ + Abort: true, + Reason: "Verification expired", + }, nil + } + return nil, nil + }). + // Hook 3: Clean up tracking after settlement + OnAfterSettle(func(ctx x402.FacilitatorSettleResultContext) error { + paymentHash := createPaymentHash(ctx.PaymentPayload) + delete(verifiedPayments, paymentHash) + return nil + }). + // Hook 4: Clean up on failure too + OnSettleFailure(func(ctx x402.FacilitatorSettleFailureContext) (*x402.FacilitatorSettleFailureHookResult, error) { + paymentHash := createPaymentHash(ctx.PaymentPayload) + delete(verifiedPayments, paymentHash) + return nil, nil + }) +``` + + +## What It Tests + +### Core Functionality +- ✅ **V2 Protocol** - Modern x402 facilitator protocol +- ✅ **V1 Protocol** - Legacy x402 facilitator protocol +- ✅ **Payment Verification** - Validates payment payloads off-chain +- ✅ **Payment Settlement** - Executes transactions on-chain +- ✅ **Multi-chain Support** - EVM and SVM mechanisms +- ✅ **HTTP API** - HTTP server exposing facilitator endpoints + +### Facilitator Endpoints +- ✅ `POST /verify` - Verifies payment payload validity +- ✅ `POST /settle` - Settles payment on blockchain +- ✅ `GET /supported` - Returns supported payment kinds +- ✅ **Extension Support** - Bazaar discovery extension + +## What It Demonstrates + +### Facilitator Setup + +```go +import ( + x402 "github.com/coinbase/x402/go" + "github.com/coinbase/x402/go/mechanisms/evm" + evmv1 "github.com/coinbase/x402/go/mechanisms/evm/exact/v1" + "github.com/coinbase/x402/go/mechanisms/svm" + svmv1 "github.com/coinbase/x402/go/mechanisms/svm/exact/v1" + "github.com/coinbase/x402/go/extensions/bazaar" +) + +// Create facilitator +facilitator := x402.Newx402Facilitator() +facilitator.RegisterExtension(bazaar.EXTENSION_NAME) + +// Register EVM V2 wildcard +evmFacilitator := evm.NewExactEvmFacilitator(evmSigner) +facilitator.Register("eip155:*", evmFacilitator) + +// Register EVM V1 networks +evmFacilitatorV1 := evmv1.NewExactEvmFacilitatorV1(evmSigner) +facilitator.RegisterV1("base-sepolia", evmFacilitatorV1) + +// Register SVM V2 wildcard +svmFacilitator := svm.NewExactSvmFacilitator(svmSigner) +facilitator.Register("solana:*", svmFacilitator) + +// Register SVM V1 networks +svmFacilitatorV1 := svmv1.NewExactSvmFacilitatorV1(svmSigner) +facilitator.RegisterV1("solana-devnet", svmFacilitatorV1) +``` + +### HTTP Server + +```go +import ( + "net/http" + "encoding/json" +) + +http.HandleFunc("/verify", handleVerify(facilitator)) +http.HandleFunc("/settle", handleSettle(facilitator)) +http.HandleFunc("/supported", handleSupported(facilitator)) + +http.ListenAndServe(":4024", nil) +``` + +### Key Concepts Shown + +1. **Extension Registration** - Bazaar discovery support +2. **Multi-Version Support** - V1 and V2 protocols +3. **Multi-Chain Support** - EVM and SVM mechanisms +4. **Wildcard Registration** - Efficient V2 scheme handling +5. **Real Settlement** - Actual on-chain transaction execution +6. **Error Handling** - Comprehensive verification errors + +## Test Scenarios + +This facilitator is tested with: +- **Clients:** TypeScript Fetch, Go HTTP +- **Servers:** Express (TypeScript), Gin (Go) +- **Networks:** Base Sepolia (EVM), Solana Devnet (SVM) +- **Protocols:** V1 and V2 + +### Verification Flow +1. Receives payment payload + requirements +2. Validates signatures and authorization structure +3. Returns verification result without blockchain interaction + +### Settlement Flow +1. Receives payment payload + requirements +2. Verifies payload validity +3. Executes transaction on blockchain +4. Returns transaction hash and status + +## Running + +```bash +# Via e2e test suite +cd e2e +pnpm test --facilitator=go + +# Direct execution +cd e2e/facilitators/go +export EVM_PRIVATE_KEY="0x..." +export SVM_PRIVATE_KEY="..." +export PORT=4024 +./go +``` + +## Environment Variables + +- `PORT` - HTTP server port (default: 4024) +- `EVM_PRIVATE_KEY` - Ethereum private key for settlement +- `SVM_PRIVATE_KEY` - Solana private key for settlement + +## API Endpoints + +### POST /verify + +**Request:** +```json +{ + "x402Version": 2, + "paymentPayload": { ... }, + "paymentRequirements": { ... } +} +``` + +**Response:** +```json +{ + "isValid": true, + "payer": "0x...", + "scheme": "exact", + "network": "eip155:84532" +} +``` + +### POST /settle + +**Request:** +```json +{ + "x402Version": 2, + "paymentPayload": { ... }, + "paymentRequirements": { ... } +} +``` + +**Response:** +```json +{ + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x...", + "scheme": "exact" +} +``` + +### GET /supported + +**Response:** +```json +{ + "kinds": [ + { + "scheme": "exact", + "network": "eip155:84532", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "extensions": ["bazaar"] + } + ] +} +``` + +## Implementation Details + +### EVM Facilitator +- Verifies EIP-712 signatures +- Calls `transferWithAuthorization()` on USDC contract +- Uses go-ethereum for blockchain interaction +- Handles gas estimation and transaction submission + +### SVM Facilitator +- Verifies ed25519 signatures +- Completes partially-signed SPL Token transactions +- Adds fee payer signature +- Submits to Solana RPC + +### Extension Support +- **Bazaar** - Discovery extension for API documentation +- Registered at facilitator level +- Included in supported kinds response + +## Dependencies + +- `github.com/coinbase/x402/go` - Core facilitator +- `github.com/coinbase/x402/go/mechanisms/evm` - EVM mechanisms +- `github.com/coinbase/x402/go/mechanisms/svm` - SVM mechanisms +- `github.com/coinbase/x402/go/extensions/bazaar` - Bazaar extension +- `github.com/ethereum/go-ethereum` - Ethereum client +- `github.com/gagliardetto/solana-go` - Solana client diff --git a/e2e/facilitators/go/bazaar.go b/e2e/facilitators/go/bazaar.go new file mode 100644 index 000000000..a0b4313ee --- /dev/null +++ b/e2e/facilitators/go/bazaar.go @@ -0,0 +1,86 @@ +package main + +import ( + "log" + "sync" + "time" + + x402 "github.com/coinbase/x402/go" + exttypes "github.com/coinbase/x402/go/extensions/types" +) + +type DiscoveredResource struct { + Resource string `json:"resource"` + Type string `json:"type"` + X402Version int `json:"x402Version"` + Accepts []x402.PaymentRequirements `json:"accepts"` + DiscoveryInfo *exttypes.DiscoveryInfo `json:"discoveryInfo,omitempty"` + LastUpdated string `json:"lastUpdated"` + Metadata map[string]interface{} `json:"metadata,omitempty"` +} + +type BazaarCatalog struct { + discoveredResources map[string]DiscoveredResource + mutex *sync.RWMutex +} + +func NewBazaarCatalog() *BazaarCatalog { + return &BazaarCatalog{ + discoveredResources: make(map[string]DiscoveredResource), + mutex: &sync.RWMutex{}, + } +} + +func (c *BazaarCatalog) CatalogResource( + resourceURL string, + method string, + x402Version int, + discoveryInfo *exttypes.DiscoveryInfo, + paymentRequirements x402.PaymentRequirements, +) { + log.Printf("📝 Discovered resource: %s", resourceURL) + log.Printf(" Method: %s", method) + log.Printf(" x402 Version: %d", x402Version) + + c.mutex.Lock() + defer c.mutex.Unlock() + + c.discoveredResources[resourceURL] = DiscoveredResource{ + Resource: resourceURL, + Type: "http", + X402Version: x402Version, + Accepts: []x402.PaymentRequirements{paymentRequirements}, + DiscoveryInfo: discoveryInfo, + LastUpdated: time.Now().Format(time.RFC3339), + Metadata: make(map[string]interface{}), + } +} + +func (c *BazaarCatalog) GetResources(limit, offset int) ([]DiscoveredResource, int) { + c.mutex.RLock() + defer c.mutex.RUnlock() + + all := make([]DiscoveredResource, 0, len(c.discoveredResources)) + for _, r := range c.discoveredResources { + all = append(all, r) + } + + total := len(all) + if offset >= total { + return []DiscoveredResource{}, total + } + + end := offset + limit + if end > total { + end = total + } + + return all[offset:end], total +} + +func (c *BazaarCatalog) GetCount() int { + c.mutex.RLock() + defer c.mutex.RUnlock() + + return len(c.discoveredResources) +} diff --git a/e2e/facilitators/go/build.sh b/e2e/facilitators/go/build.sh new file mode 100755 index 000000000..04d17f05b --- /dev/null +++ b/e2e/facilitators/go/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Building Go facilitator..." +go build -o go . +echo "✅ Build completed: go" + diff --git a/e2e/facilitators/go/facilitator b/e2e/facilitators/go/facilitator new file mode 100755 index 000000000..7643e7bea Binary files /dev/null and b/e2e/facilitators/go/facilitator differ diff --git a/e2e/facilitators/go/go b/e2e/facilitators/go/go new file mode 100755 index 000000000..8b1e811bd Binary files /dev/null and b/e2e/facilitators/go/go differ diff --git a/e2e/facilitators/go/go.mod b/e2e/facilitators/go/go.mod new file mode 100644 index 000000000..889ac0817 --- /dev/null +++ b/e2e/facilitators/go/go.mod @@ -0,0 +1,91 @@ +module github.com/coinbase/x402-go/e2e/facilitators/go + +go 1.24.0 + +toolchain go1.24.1 + +require ( + github.com/coinbase/x402/go v0.0.0 + github.com/ethereum/go-ethereum v1.16.7 + github.com/gagliardetto/solana-go v1.14.0 + github.com/gin-gonic/gin v1.11.0 +) + +require ( + filippo.io/edwards25519 v1.0.0-rc.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/blendle/zapdriver v1.3.1 // indirect + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gagliardetto/binary v0.8.0 // indirect + github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.27.0 // indirect + github.com/goccy/go-json v0.10.4 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.55.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + go.mongodb.org/mongo-driver v1.12.2 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/ratelimit v0.2.0 // indirect + go.uber.org/zap v1.21.0 // indirect + golang.org/x/arch v0.20.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/time v0.9.0 // indirect + golang.org/x/tools v0.36.0 // indirect + google.golang.org/protobuf v1.36.9 // indirect +) + +replace github.com/coinbase/x402/go => ../../../go diff --git a/e2e/facilitators/go/go.sum b/e2e/facilitators/go/go.sum new file mode 100644 index 000000000..da343d102 --- /dev/null +++ b/e2e/facilitators/go/go.sum @@ -0,0 +1,380 @@ +filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= +github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0= +github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= +github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= +github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= +github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= +github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= +github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= +github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw= +github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= +github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg= +github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= +github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= +github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s= +github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8= +github.com/ethereum/go-ethereum v1.16.7 h1:qeM4TvbrWK0UC0tgkZ7NiRsmBGwsjqc64BHo20U59UQ= +github.com/ethereum/go-ethereum v1.16.7/go.mod h1:Fs6QebQbavneQTYcA39PEKv2+zIjX7rPUZ14DER46wk= +github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= +github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= +github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= +github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= +github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= +github.com/gagliardetto/solana-go v1.14.0 h1:3WfAi70jOOjAJ0deFMjdhFYlLXATF4tOQXsDNWJtOLw= +github.com/gagliardetto/solana-go v1.14.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= +github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= +github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= +github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= +github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= +github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db h1:IZUYC/xb3giYwBLMnr8d0TGTzPKFGNTCGgGLoyeX330= +github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db/go.mod h1:xTEYN9KCHxuYHs+NmrmzFcnvHMzLLNiGFafCb1n3Mfg= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0= +github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ= +github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk= +github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA= +github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.12.2 h1:gbWY1bJkkmUB9jjZzcdhOL8O85N9H+Vvsf2yFN0RDws= +go.mongodb.org/mongo-driver v1.12.2/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= +go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA= +go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c= +golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/e2e/facilitators/go/install.sh b/e2e/facilitators/go/install.sh new file mode 100755 index 000000000..a9ea0d4c5 --- /dev/null +++ b/e2e/facilitators/go/install.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Installing Go dependencies for facilitator..." +go mod tidy +echo "✅ Dependencies installed" + diff --git a/e2e/facilitators/go/main.go b/e2e/facilitators/go/main.go new file mode 100644 index 000000000..38f9384f0 --- /dev/null +++ b/e2e/facilitators/go/main.go @@ -0,0 +1,1047 @@ +package main + +import ( + "bytes" + "context" + "crypto/ecdsa" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "log" + "math/big" + "net/http" + "os" + "strings" + "sync" + "time" + + x402 "github.com/coinbase/x402/go" + "github.com/coinbase/x402/go/extensions/bazaar" + exttypes "github.com/coinbase/x402/go/extensions/types" + evmmech "github.com/coinbase/x402/go/mechanisms/evm" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/facilitator" + evmv1 "github.com/coinbase/x402/go/mechanisms/evm/exact/v1/facilitator" + svmmech "github.com/coinbase/x402/go/mechanisms/svm" + svm "github.com/coinbase/x402/go/mechanisms/svm/exact/facilitator" + svmv1 "github.com/coinbase/x402/go/mechanisms/svm/exact/v1/facilitator" + x402types "github.com/coinbase/x402/go/types" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/signer/core/apitypes" + solana "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + "github.com/gin-gonic/gin" +) + +// NOTE: Facilitator signer helpers (go/signers/evm and go/signers/svm) are not yet implemented. +// When available, this will reduce 300+ lines of facilitator signer code to just a few lines. +// For now, facilitator signers still require manual implementation. +// See PROPOSAL_SIGNER_HELPERS.md for the planned facilitator signer helpers. + +const ( + DefaultPort = "4022" + Network = "eip155:84532" + Scheme = "exact" +) + +// Request/Response types +type VerifyRequest struct { + X402Version int `json:"x402Version"` + PaymentPayload json.RawMessage `json:"paymentPayload"` + PaymentRequirements json.RawMessage `json:"paymentRequirements"` +} + +type SettleRequest struct { + X402Version int `json:"x402Version"` + PaymentPayload json.RawMessage `json:"paymentPayload"` + PaymentRequirements json.RawMessage `json:"paymentRequirements"` +} + +// Real EVM signer for facilitator using ethclient +type realFacilitatorEvmSigner struct { + privateKey *ecdsa.PrivateKey + address common.Address + client *ethclient.Client + chainID *big.Int +} + +func newRealFacilitatorEvmSigner(privateKeyHex string, rpcURL string) (*realFacilitatorEvmSigner, error) { + // Remove 0x prefix if present + privateKeyHex = strings.TrimPrefix(privateKeyHex, "0x") + + privateKey, err := crypto.HexToECDSA(privateKeyHex) + if err != nil { + return nil, fmt.Errorf("failed to parse private key: %w", err) + } + + address := crypto.PubkeyToAddress(privateKey.PublicKey) + + // Connect to blockchain + client, err := ethclient.Dial(rpcURL) + if err != nil { + return nil, fmt.Errorf("failed to connect to RPC: %w", err) + } + + // Get chain ID + ctx := context.Background() + chainID, err := client.ChainID(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get chain ID: %w", err) + } + + return &realFacilitatorEvmSigner{ + privateKey: privateKey, + address: address, + client: client, + chainID: chainID, + }, nil +} + +func (s *realFacilitatorEvmSigner) GetAddresses() []string { + return []string{s.address.Hex()} +} + +func (s *realFacilitatorEvmSigner) GetChainID(ctx context.Context) (*big.Int, error) { + return s.chainID, nil +} + +func (s *realFacilitatorEvmSigner) VerifyTypedData( + ctx context.Context, + address string, + domain evmmech.TypedDataDomain, + types map[string][]evmmech.TypedDataField, + primaryType string, + message map[string]interface{}, + signature []byte, +) (bool, error) { + // Convert to apitypes for EIP-712 verification + chainId := getBigIntFromInterface(domain.ChainID) + typedData := apitypes.TypedData{ + Types: make(apitypes.Types), + PrimaryType: primaryType, + Domain: apitypes.TypedDataDomain{ + Name: getStringFromInterface(domain.Name), + Version: getStringFromInterface(domain.Version), + ChainId: (*math.HexOrDecimal256)(chainId), + VerifyingContract: getStringFromInterface(domain.VerifyingContract), + }, + Message: message, + } + + // Convert types + for typeName, fields := range types { + typedFields := make([]apitypes.Type, len(fields)) + for i, field := range fields { + typedFields[i] = apitypes.Type{ + Name: field.Name, + Type: field.Type, + } + } + typedData.Types[typeName] = typedFields + } + + // Add EIP712Domain if not present + if _, exists := typedData.Types["EIP712Domain"]; !exists { + typedData.Types["EIP712Domain"] = []apitypes.Type{ + {Name: "name", Type: "string"}, + {Name: "version", Type: "string"}, + {Name: "chainId", Type: "uint256"}, + {Name: "verifyingContract", Type: "address"}, + } + } + + // Hash the data + dataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message) + if err != nil { + return false, fmt.Errorf("failed to hash struct: %w", err) + } + + domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map()) + if err != nil { + return false, fmt.Errorf("failed to hash domain: %w", err) + } + + rawData := []byte{0x19, 0x01} + rawData = append(rawData, domainSeparator...) + rawData = append(rawData, dataHash...) + digest := crypto.Keccak256(rawData) + + // Recover the address from signature + if len(signature) != 65 { + return false, fmt.Errorf("invalid signature length: %d", len(signature)) + } + + // Adjust v value + v := signature[64] + if v >= 27 { + v -= 27 + } + + sigCopy := make([]byte, 65) + copy(sigCopy, signature) + sigCopy[64] = v + + pubKey, err := crypto.SigToPub(digest, sigCopy) + if err != nil { + return false, fmt.Errorf("failed to recover public key: %w", err) + } + + recoveredAddr := crypto.PubkeyToAddress(*pubKey) + expectedAddr := common.HexToAddress(address) + + return bytes.Equal(recoveredAddr.Bytes(), expectedAddr.Bytes()), nil +} + +func (s *realFacilitatorEvmSigner) ReadContract( + ctx context.Context, + contractAddress string, + abiJSON []byte, + method string, + args ...interface{}, +) (interface{}, error) { + // Parse ABI + contractABI, err := abi.JSON(strings.NewReader(string(abiJSON))) + if err != nil { + return nil, fmt.Errorf("failed to parse ABI: %w", err) + } + + // Pack the method call + data, err := contractABI.Pack(method, args...) + if err != nil { + return nil, fmt.Errorf("failed to pack method call: %w", err) + } + + // Make the call + to := common.HexToAddress(contractAddress) + + // Check if contract exists at this address + code, err := s.client.CodeAt(ctx, to, nil) + if err != nil { + log.Printf("Failed to check contract code: contract=%s, error=%v", contractAddress, err) + } else if len(code) == 0 { + log.Printf("WARNING: No contract code at address %s", contractAddress) + } + + msg := ethereum.CallMsg{ + To: &to, + Data: data, + } + + result, err := s.client.CallContract(ctx, msg, nil) + if err != nil { + log.Printf("Contract call failed: method=%s, contract=%s, error=%v", method, contractAddress, err) + return nil, fmt.Errorf("failed to call contract: %w", err) + } + + log.Printf("Contract call: method=%s, contract=%s, dataLen=%d, resultLen=%d, result=%x", method, contractAddress, len(data), len(result), result) + + // Handle empty result (some contract calls return nothing or revert) + if len(result) == 0 { + // For authorizationState, empty means false (nonce not used) + if method == "authorizationState" { + return false, nil + } + // For balanceOf or allowance, empty might mean 0 + if method == "balanceOf" || method == "allowance" { + return big.NewInt(0), nil + } + return nil, fmt.Errorf("empty result from contract call") + } + + // Unpack the result based on method + method_obj, exists := contractABI.Methods[method] + if !exists { + return nil, fmt.Errorf("method %s not found in ABI", method) + } + + output, err := method_obj.Outputs.Unpack(result) + if err != nil { + return nil, fmt.Errorf("failed to unpack result: %w", err) + } + + // Return the first output (most contract reads return a single value) + if len(output) > 0 { + return output[0], nil + } + + return nil, nil +} + +func (s *realFacilitatorEvmSigner) WriteContract( + ctx context.Context, + contractAddress string, + abiJSON []byte, + method string, + args ...interface{}, +) (string, error) { + // Parse ABI + contractABI, err := abi.JSON(strings.NewReader(string(abiJSON))) + if err != nil { + return "", fmt.Errorf("failed to parse ABI: %w", err) + } + + // Pack the method call + data, err := contractABI.Pack(method, args...) + if err != nil { + return "", fmt.Errorf("failed to pack method call: %w", err) + } + + // Get nonce + nonce, err := s.client.PendingNonceAt(ctx, s.address) + if err != nil { + return "", fmt.Errorf("failed to get nonce: %w", err) + } + + // Get gas price + gasPrice, err := s.client.SuggestGasPrice(ctx) + if err != nil { + return "", fmt.Errorf("failed to get gas price: %w", err) + } + + // Create transaction + to := common.HexToAddress(contractAddress) + tx := types.NewTransaction( + nonce, + to, + big.NewInt(0), // value + 300000, // gas limit + gasPrice, + data, + ) + + // Sign transaction + signedTx, err := types.SignTx(tx, types.LatestSignerForChainID(s.chainID), s.privateKey) + if err != nil { + return "", fmt.Errorf("failed to sign transaction: %w", err) + } + + // Send transaction + err = s.client.SendTransaction(ctx, signedTx) + if err != nil { + return "", fmt.Errorf("failed to send transaction: %w", err) + } + + return signedTx.Hash().Hex(), nil +} + +func (s *realFacilitatorEvmSigner) SendTransaction( + ctx context.Context, + to string, + data []byte, +) (string, error) { + // Get nonce + nonce, err := s.client.PendingNonceAt(ctx, s.address) + if err != nil { + return "", fmt.Errorf("failed to get nonce: %w", err) + } + + // Get gas price + gasPrice, err := s.client.SuggestGasPrice(ctx) + if err != nil { + return "", fmt.Errorf("failed to get gas price: %w", err) + } + + // Create transaction with raw data + toAddr := common.HexToAddress(to) + tx := types.NewTransaction( + nonce, + toAddr, + big.NewInt(0), // value + 300000, // gas limit + gasPrice, + data, + ) + + // Sign transaction + signedTx, err := types.SignTx(tx, types.LatestSignerForChainID(s.chainID), s.privateKey) + if err != nil { + return "", fmt.Errorf("failed to sign transaction: %w", err) + } + + // Send transaction + err = s.client.SendTransaction(ctx, signedTx) + if err != nil { + return "", fmt.Errorf("failed to send transaction: %w", err) + } + + return signedTx.Hash().Hex(), nil +} + +func (s *realFacilitatorEvmSigner) WaitForTransactionReceipt(ctx context.Context, txHash string) (*evmmech.TransactionReceipt, error) { + hash := common.HexToHash(txHash) + + // Poll for receipt + for i := 0; i < 30; i++ { // 30 seconds timeout + receipt, err := s.client.TransactionReceipt(ctx, hash) + if err == nil && receipt != nil { + return &evmmech.TransactionReceipt{ + Status: uint64(receipt.Status), + BlockNumber: receipt.BlockNumber.Uint64(), + TxHash: receipt.TxHash.Hex(), + }, nil + } + time.Sleep(1 * time.Second) + } + + return nil, fmt.Errorf("transaction receipt not found after 30 seconds") +} + +func (s *realFacilitatorEvmSigner) GetBalance(ctx context.Context, address string, tokenAddress string) (*big.Int, error) { + if tokenAddress == "" || tokenAddress == "0x0000000000000000000000000000000000000000" { + // Native balance + balance, err := s.client.BalanceAt(ctx, common.HexToAddress(address), nil) + if err != nil { + return nil, fmt.Errorf("failed to get balance: %w", err) + } + return balance, nil + } + + // ERC20 balance - need to call balanceOf + // Minimal ERC20 ABI for balanceOf + const erc20ABI = `[{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"}]` + + // Convert address to common.Address for ABI packing + result, err := s.ReadContract(ctx, tokenAddress, []byte(erc20ABI), "balanceOf", common.HexToAddress(address)) + if err != nil { + return nil, err + } + + if balance, ok := result.(*big.Int); ok { + return balance, nil + } + + return nil, fmt.Errorf("unexpected balance type: %T", result) +} + +func (s *realFacilitatorEvmSigner) GetCode(ctx context.Context, address string) ([]byte, error) { + addr := common.HexToAddress(address) + code, err := s.client.CodeAt(ctx, addr, nil) + if err != nil { + return nil, fmt.Errorf("failed to get code: %w", err) + } + return code, nil +} + +// Helper functions for type conversion +func getStringFromInterface(v interface{}) string { + if v == nil { + return "" + } + switch val := v.(type) { + case string: + return val + case *string: + if val != nil { + return *val + } + } + return "" +} + +func getBigIntFromInterface(v interface{}) *big.Int { + if v == nil { + return big.NewInt(0) + } + switch val := v.(type) { + case *big.Int: + return val + case int64: + return big.NewInt(val) + case string: + n, _ := new(big.Int).SetString(val, 10) + return n + } + return big.NewInt(0) +} + +var ( + bazaarCatalog = NewBazaarCatalog() + verifiedPayments = make(map[string]int64) + verificationMutex = &sync.RWMutex{} +) + +func createPaymentHash(paymentPayload x402.PaymentPayload) string { + data, _ := json.Marshal(paymentPayload) + hash := sha256.Sum256(data) + return hex.EncodeToString(hash[:]) +} + +// Real SVM facilitator signer +type realFacilitatorSvmSigner struct { + privateKey solana.PrivateKey + rpcClients map[string]*rpc.Client + rpcURL string +} + +func newRealFacilitatorSvmSigner(privateKeyBase58 string, rpcURL string) (*realFacilitatorSvmSigner, error) { + privateKey, err := solana.PrivateKeyFromBase58(privateKeyBase58) + if err != nil { + return nil, fmt.Errorf("failed to parse Solana private key: %w", err) + } + + return &realFacilitatorSvmSigner{ + privateKey: privateKey, + rpcClients: make(map[string]*rpc.Client), + rpcURL: rpcURL, + }, nil +} + +// getRPC is a private helper method to get RPC client for a network +func (s *realFacilitatorSvmSigner) getRPC(ctx context.Context, network string) (*rpc.Client, error) { + if client, ok := s.rpcClients[network]; ok { + return client, nil + } + + rpcURL := s.rpcURL + if rpcURL == "" { + config, err := svmmech.GetNetworkConfig(network) + if err != nil { + return nil, err + } + rpcURL = config.RPCURL + } + + client := rpc.New(rpcURL) + s.rpcClients[network] = client + return client, nil +} + +func (s *realFacilitatorSvmSigner) SignTransaction(ctx context.Context, tx *solana.Transaction, feePayer solana.PublicKey, network string) error { + // Verify feePayer matches our key + if feePayer != s.privateKey.PublicKey() { + return fmt.Errorf("no signer for feePayer %s. Available: %s", feePayer, s.privateKey.PublicKey()) + } + + messageBytes, err := tx.Message.MarshalBinary() + if err != nil { + return fmt.Errorf("failed to marshal message: %w", err) + } + + signature, err := s.privateKey.Sign(messageBytes) + if err != nil { + return fmt.Errorf("failed to sign: %w", err) + } + + accountIndex, err := tx.GetAccountIndex(s.privateKey.PublicKey()) + if err != nil { + return fmt.Errorf("failed to get account index: %w", err) + } + + if len(tx.Signatures) <= int(accountIndex) { + newSignatures := make([]solana.Signature, accountIndex+1) + copy(newSignatures, tx.Signatures) + tx.Signatures = newSignatures + } + + tx.Signatures[accountIndex] = signature + return nil +} + +func (s *realFacilitatorSvmSigner) SimulateTransaction(ctx context.Context, tx *solana.Transaction, network string) error { + rpcClient, err := s.getRPC(ctx, network) + if err != nil { + return err + } + + opts := rpc.SimulateTransactionOpts{ + SigVerify: true, + ReplaceRecentBlockhash: false, + Commitment: svmmech.DefaultCommitment, + } + + simResult, err := rpcClient.SimulateTransactionWithOpts(ctx, tx, &opts) + if err != nil { + return fmt.Errorf("simulation failed: %w", err) + } + + if simResult != nil && simResult.Value != nil && simResult.Value.Err != nil { + return fmt.Errorf("simulation failed: transaction would fail on-chain") + } + + return nil +} + +func (s *realFacilitatorSvmSigner) SendTransaction(ctx context.Context, tx *solana.Transaction, network string) (solana.Signature, error) { + rpcClient, err := s.getRPC(ctx, network) + if err != nil { + return solana.Signature{}, err + } + + sig, err := rpcClient.SendTransactionWithOpts(ctx, tx, rpc.TransactionOpts{ + SkipPreflight: true, + PreflightCommitment: svmmech.DefaultCommitment, + }) + if err != nil { + return solana.Signature{}, fmt.Errorf("failed to send transaction: %w", err) + } + + return sig, nil +} + +func (s *realFacilitatorSvmSigner) ConfirmTransaction(ctx context.Context, signature solana.Signature, network string) error { + rpcClient, err := s.getRPC(ctx, network) + if err != nil { + return err + } + + for attempt := 0; attempt < svmmech.MaxConfirmAttempts; attempt++ { + // Check for context cancellation + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + // Try getSignatureStatuses first (faster) + statuses, err := rpcClient.GetSignatureStatuses(ctx, true, signature) + if err == nil && statuses != nil && statuses.Value != nil && len(statuses.Value) > 0 { + status := statuses.Value[0] + if status != nil { + if status.Err != nil { + return fmt.Errorf("transaction failed on-chain") + } + if status.ConfirmationStatus == rpc.ConfirmationStatusConfirmed || + status.ConfirmationStatus == rpc.ConfirmationStatusFinalized { + return nil + } + } + } + + // Fallback to getTransaction + if err != nil { + txResult, txErr := rpcClient.GetTransaction(ctx, signature, &rpc.GetTransactionOpts{ + Encoding: solana.EncodingBase58, + Commitment: svmmech.DefaultCommitment, + }) + + if txErr == nil && txResult != nil && txResult.Meta != nil { + if txResult.Meta.Err != nil { + return fmt.Errorf("transaction failed on-chain") + } + return nil + } + } + + // Wait before retrying + time.Sleep(svmmech.ConfirmRetryDelay) + } + + return fmt.Errorf("transaction confirmation timed out after %d attempts", svmmech.MaxConfirmAttempts) +} + +func (s *realFacilitatorSvmSigner) GetAddresses(ctx context.Context, network string) []solana.PublicKey { + return []solana.PublicKey{s.privateKey.PublicKey()} +} + +func main() { + // Get configuration from environment + port := os.Getenv("PORT") + if port == "" { + port = DefaultPort + } + + evmPrivateKey := os.Getenv("EVM_PRIVATE_KEY") + if evmPrivateKey == "" { + log.Fatal("❌ EVM_PRIVATE_KEY environment variable is required") + } + + svmPrivateKey := os.Getenv("SVM_PRIVATE_KEY") + if svmPrivateKey == "" { + log.Fatal("❌ SVM_PRIVATE_KEY environment variable is required") + } + + // Initialize the real EVM blockchain signer (uses default Base Sepolia RPC) + evmSigner, err := newRealFacilitatorEvmSigner(evmPrivateKey, "https://sepolia.base.org") + if err != nil { + log.Fatalf("Failed to create EVM signer: %v", err) + } + + chainID, _ := evmSigner.GetChainID(context.Background()) + addresses := evmSigner.GetAddresses() + log.Printf("EVM Facilitator account: %s", addresses[0]) + log.Printf("Connected to chain ID: %s (expected: 84532 for Base Sepolia)", chainID.String()) + + // Initialize the real SVM blockchain signer (uses default Solana Devnet RPC) + svmSigner, err := newRealFacilitatorSvmSigner(svmPrivateKey, "https://api.devnet.solana.com") + if err != nil { + log.Fatalf("Failed to create SVM signer: %v", err) + } + + svmAddresses := svmSigner.GetAddresses(context.Background(), "solana-devnet") + log.Printf("SVM Facilitator account: %s", svmAddresses[0].String()) + + // Initialize the x402 Facilitator with EVM and SVM support + facilitator := x402.Newx402Facilitator() + + // Register EVM schemes with network arrays + // Enable smart wallet deployment via EIP-6492 + evmConfig := &evm.ExactEvmSchemeConfig{ + DeployERC4337WithEIP6492: true, + } + evmFacilitatorScheme := evm.NewExactEvmScheme(evmSigner, evmConfig) + facilitator.Register([]x402.Network{"eip155:84532"}, evmFacilitatorScheme) + + evmV1Config := &evmv1.ExactEvmSchemeV1Config{ + DeployERC4337WithEIP6492: true, + } + evmFacilitatorV1Scheme := evmv1.NewExactEvmSchemeV1(evmSigner, evmV1Config) + facilitator.RegisterV1([]x402.Network{"base-sepolia"}, evmFacilitatorV1Scheme) + + // Register SVM schemes with network arrays + svmFacilitatorScheme := svm.NewExactSvmScheme(svmSigner) + facilitator.Register([]x402.Network{"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"}, svmFacilitatorScheme) // Devnet + + svmFacilitatorV1Scheme := svmv1.NewExactSvmSchemeV1(svmSigner) + facilitator.RegisterV1([]x402.Network{"solana-devnet"}, svmFacilitatorV1Scheme) + + // Register the Bazaar discovery extension + facilitator.RegisterExtension(exttypes.BAZAAR) + + // Lifecycle hooks for payment tracking and discovery + facilitator. + OnAfterVerify(func(ctx x402.FacilitatorVerifyResultContext) error { + // Hook 1: Track verified payment for verify→settle flow validation + if ctx.Result.IsValid { + // Hooks now use view interfaces - create hash from payload view + paymentHash := fmt.Sprintf("v%d-%s-%s", + ctx.Payload.GetVersion(), + ctx.Payload.GetScheme(), + ctx.Payload.GetNetwork()) + verificationMutex.Lock() + verifiedPayments[paymentHash] = time.Now().Unix() + verificationMutex.Unlock() + + log.Printf("✅ Payment verified: %s", paymentHash) + + // Hook 2: Extract and catalog Bazaar discovery info using bazaar package + discovered, err := bazaar.ExtractDiscoveredResourceFromPaymentPayload( + ctx.PayloadBytes, + ctx.RequirementsBytes, + true, // validate + ) + if err != nil { + log.Printf("Warning: Failed to extract discovery info: %v", err) + } else if discovered != nil { + log.Printf("📝 Cataloging discovered resource: %s %s", discovered.Method, discovered.ResourceURL) + + // Unmarshal requirements for cataloging based on version + version := ctx.Payload.GetVersion() + if version == 2 { + var requirements x402.PaymentRequirements + if err := json.Unmarshal(ctx.RequirementsBytes, &requirements); err == nil { + bazaarCatalog.CatalogResource( + discovered.ResourceURL, + discovered.Method, + version, + discovered.DiscoveryInfo, + requirements, + ) + } + } else if version == 1 { + var requirementsV1 x402types.PaymentRequirementsV1 + if err := json.Unmarshal(ctx.RequirementsBytes, &requirementsV1); err == nil { + // Convert V1 requirements to V2 format for catalog + // This is acceptable for e2e testing as catalog interface expects V2 + requirements := x402.PaymentRequirements{ + Scheme: requirementsV1.Scheme, + Network: requirementsV1.Network, + Asset: requirementsV1.Asset, + Amount: requirementsV1.MaxAmountRequired, // V1 uses maxAmountRequired + PayTo: requirementsV1.PayTo, + MaxTimeoutSeconds: requirementsV1.MaxTimeoutSeconds, + } + bazaarCatalog.CatalogResource( + discovered.ResourceURL, + discovered.Method, + version, + discovered.DiscoveryInfo, + requirements, + ) + } + } + } + } + return nil + }). + OnBeforeSettle(func(ctx x402.FacilitatorSettleContext) (*x402.FacilitatorBeforeHookResult, error) { + // Hook 3: Validate payment was previously verified + paymentHash := fmt.Sprintf("v%d-%s-%s", + ctx.Payload.GetVersion(), + ctx.Payload.GetScheme(), + ctx.Payload.GetNetwork()) + verificationMutex.RLock() + verificationTimestamp, verified := verifiedPayments[paymentHash] + verificationMutex.RUnlock() + + if !verified { + return &x402.FacilitatorBeforeHookResult{ + Abort: true, + Reason: "Payment must be verified before settlement", + }, nil + } + + // Check verification isn't too old (5 minute timeout) + age := time.Now().Unix() - verificationTimestamp + if age > 5*60 { + verificationMutex.Lock() + delete(verifiedPayments, paymentHash) + verificationMutex.Unlock() + + return &x402.FacilitatorBeforeHookResult{ + Abort: true, + Reason: "Payment verification expired (must settle within 5 minutes)", + }, nil + } + + return nil, nil + }). + OnAfterSettle(func(ctx x402.FacilitatorSettleResultContext) error { + // Hook 4: Clean up verified payment tracking after successful settlement + paymentHash := fmt.Sprintf("v%d-%s-%s", + ctx.Payload.GetVersion(), + ctx.Payload.GetScheme(), + ctx.Payload.GetNetwork()) + verificationMutex.Lock() + delete(verifiedPayments, paymentHash) + verificationMutex.Unlock() + + if ctx.Result.Success { + log.Printf("✅ Settlement completed: %s", ctx.Result.Transaction) + } + return nil + }). + OnSettleFailure(func(ctx x402.FacilitatorSettleFailureContext) (*x402.FacilitatorSettleFailureHookResult, error) { + // Hook 5: Clean up verified payment tracking on failure too + paymentHash := fmt.Sprintf("v%d-%s-%s", + ctx.Payload.GetVersion(), + ctx.Payload.GetScheme(), + ctx.Payload.GetNetwork()) + verificationMutex.Lock() + delete(verifiedPayments, paymentHash) + verificationMutex.Unlock() + + log.Printf("❌ Settlement failed: %v", ctx.Error) + return nil, nil + }) + + // Set up Gin router + gin.SetMode(gin.ReleaseMode) + router := gin.New() + router.Use(gin.Recovery()) + + // POST /verify - Verify a payment against requirements + // Note: Payment tracking and bazaar discovery are handled by lifecycle hooks + router.POST("/verify", func(c *gin.Context) { + // First, peek at the version to determine which struct to use + var versionCheck struct { + X402Version int `json:"x402Version"` + } + + // Read body into buffer so we can parse it twice + bodyBytes, err := c.GetRawData() + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("Failed to read request body: %v", err), + }) + return + } + + // Parse version + if err := json.Unmarshal(bodyBytes, &versionCheck); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("Failed to parse version: %v", err), + }) + return + } + + var req VerifyRequest + if err := json.Unmarshal(bodyBytes, &req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("Invalid request: %v", err), + }) + return + } + + // Hooks will automatically: + // - Track verified payment (OnAfterVerify) + // - Extract and catalog discovery info (OnAfterVerify) + + // json.RawMessage is already []byte, so we can use it directly + // This preserves the exact JSON without re-marshaling (important for v1/v2 compatibility) + response, err := facilitator.Verify( + context.Background(), + []byte(req.PaymentPayload), + []byte(req.PaymentRequirements), + ) + if err != nil { + log.Printf("Verify error: %v", err) + c.JSON(http.StatusInternalServerError, gin.H{ + "error": err.Error(), + }) + return + } + + c.JSON(http.StatusOK, response) + }) + + // POST /settle - Settle a payment on-chain + // Note: Verification validation and cleanup are handled by lifecycle hooks + router.POST("/settle", func(c *gin.Context) { + // First, peek at the version to determine which struct to use + var versionCheck struct { + X402Version int `json:"x402Version"` + } + + // Read body into buffer so we can parse it twice + bodyBytes, err := c.GetRawData() + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("Failed to read request body: %v", err), + }) + return + } + + // Debug: Log raw request body + log.Printf("🔍 [FACILITATOR SETTLE] Received raw body: %s", string(bodyBytes)) + + // Parse version + if err := json.Unmarshal(bodyBytes, &versionCheck); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("Failed to parse version: %v", err), + }) + return + } + + var req SettleRequest + if err := json.Unmarshal(bodyBytes, &req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("Invalid request: %v", err), + }) + return + } + + // json.RawMessage is already []byte, so we can use it directly + // This preserves the exact JSON without re-marshaling (important for v1/v2 compatibility) + response, err := facilitator.Settle( + context.Background(), + []byte(req.PaymentPayload), + []byte(req.PaymentRequirements), + ) + + // Debug: Log response + log.Printf("🔍 [FACILITATOR SETTLE] Response: %+v", response) + log.Printf("🔍 [FACILITATOR SETTLE] Error: %v", err) + if err != nil { + log.Printf("Settle error: %v", err) + + // Check if this was an abort from hook + if strings.Contains(err.Error(), "settlement aborted:") { + // Return a proper SettleResponse instead of 500 error + c.JSON(http.StatusOK, x402.SettleResponse{ + Success: false, + ErrorReason: strings.TrimPrefix(err.Error(), "settlement aborted: "), + Network: "", // Network not available in error case since we don't parse the raw JSON + }) + return + } + + c.JSON(http.StatusInternalServerError, gin.H{ + "error": err.Error(), + }) + return + } + + c.JSON(http.StatusOK, response) + }) + + // GET /supported - Get supported payment kinds and extensions + router.GET("/supported", func(c *gin.Context) { + // Get supported kinds - networks already registered + response := facilitator.GetSupported() + c.JSON(http.StatusOK, response) + }) + + // GET /discovery/resources - List all discovered resources from bazaar extensions + router.GET("/discovery/resources", func(c *gin.Context) { + limit := 100 + if limitParam := c.Query("limit"); limitParam != "" { + fmt.Sscanf(limitParam, "%d", &limit) + } + + offset := 0 + if offsetParam := c.Query("offset"); offsetParam != "" { + fmt.Sscanf(offsetParam, "%d", &offset) + } + + items, total := bazaarCatalog.GetResources(limit, offset) + + c.JSON(http.StatusOK, gin.H{ + "x402Version": 1, + "items": items, + "pagination": gin.H{ + "limit": limit, + "offset": offset, + "total": total, + }, + }) + }) + + router.GET("/health", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "status": "ok", + "network": Network, + "facilitator": "go", + "version": "2.0.0", + "extensions": []string{exttypes.BAZAAR}, + "discoveredResources": bazaarCatalog.GetCount(), + }) + }) + + // POST /close - Graceful shutdown endpoint + router.POST("/close", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "message": "Facilitator shutting down gracefully", + }) + log.Println("Received shutdown request") + + // Give time for response to be sent, then exit + go func() { + time.Sleep(100 * time.Millisecond) + os.Exit(0) + }() + }) + + // Start the server + fmt.Printf(` +╔════════════════════════════════════════════════════════╗ +║ x402 Go Facilitator ║ +╠════════════════════════════════════════════════════════╣ +║ Server: http://localhost:%s ║ +║ Network: %s ║ +║ Address: %s ║ +║ Extensions: bazaar ║ +║ ║ +║ Endpoints: ║ +║ • POST /verify (verify payment) ║ +║ • POST /settle (settle payment) ║ +║ • GET /supported (get supported kinds) ║ +║ • GET /discovery/resources (list discovered) ║ +║ • GET /health (health check) ║ +║ • POST /close (shutdown server) ║ +╚════════════════════════════════════════════════════════╝ +`, port, Network, evmSigner.GetAddresses()[0]) + + // Log that facilitator is ready (needed for e2e test discovery) + log.Println("Facilitator listening") + + // Start server + if err := router.Run(":" + port); err != nil { + log.Fatalf("Failed to start server: %v", err) + } +} diff --git a/e2e/facilitators/go/run.sh b/e2e/facilitators/go/run.sh new file mode 100755 index 000000000..f03ecbcf9 --- /dev/null +++ b/e2e/facilitators/go/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +go run . diff --git a/e2e/facilitators/go/test.config.json b/e2e/facilitators/go/test.config.json new file mode 100644 index 000000000..17dc80351 --- /dev/null +++ b/e2e/facilitators/go/test.config.json @@ -0,0 +1,24 @@ +{ + "name": "go", + "type": "facilitator", + "language": "go", + "protocolFamilies": [ + "evm", + "svm" + ], + "x402Versions": [ + 1, + 2 + ], + "extensions": [ + "bazaar" + ], + "environment": { + "required": [ + "PORT", + "EVM_PRIVATE_KEY", + "SVM_PRIVATE_KEY" + ], + "optional": [] + } +} \ No newline at end of file diff --git a/e2e/facilitators/text-facilitator-protocol.txt b/e2e/facilitators/text-facilitator-protocol.txt new file mode 100644 index 000000000..ccf6c27e9 --- /dev/null +++ b/e2e/facilitators/text-facilitator-protocol.txt @@ -0,0 +1,169 @@ +# X402 Facilitator Protocol + +## CLI Interface +1. Must be runnable through a CLI command, which can be parsed from 'run.sh' +2. Must output specific logs +3. Must exit with code 0 for success, 1 for failure +4. Must run as a server listening on a specified port + +## Protocol Family Support +Facilitators must declare which protocol families they support in their test.config.json: +- **EVM**: Ethereum Virtual Machine compatible networks (Base, Ethereum, etc.) +- **SVM**: Solana Virtual Machine compatible networks (Solana, etc.) + +## X402 Version Support +Facilitators must declare which x402 protocol versions they support using the `x402Versions` field: +- **x402Versions**: Array of supported x402 protocol versions (e.g., [1, 2]) + +## Extensions Support +Facilitators must declare which protocol extensions they support using the `extensions` field: +- **extensions**: Array of supported extension names (e.g., ["bazaar"]) + +Example configuration: +```json +{ + "name": "typescript", + "type": "facilitator", + "language": "typescript", + "protocolFamilies": ["evm"], + "x402Versions": [2], + "extensions": ["bazaar"], + "environment": { + "required": ["PORT", "EVM_PRIVATE_KEY", "EVM_NETWORK"], + "optional": ["SVM_PRIVATE_KEY", "SVM_NETWORK"] + } +} +``` + +## Environment Variables / CLI Arguments +The following parameters must be configurable: +- `PORT`: Port to listen on (default: 4022) +- `EVM_PRIVATE_KEY`: Private key for EVM operations +- `SVM_PRIVATE_KEY`: Private key for Solana operations +- `EVM_NETWORK`: EVM network to use (e.g., "eip155:84532" for Base Sepolia) +- `SVM_NETWORK`: Solana network to use (e.g., "solana:devnet") + +## Required Endpoints + +### POST /verify +- **Purpose**: Verify a payment against requirements +- **Request Body**: + ```json + { + "x402Version": 2, + "paymentPayload": { + "x402Version": 2, + "scheme": "exact", + "network": "eip155:84532", + "payload": { ... }, + "accepted": { ... } + }, + "paymentRequirements": { + "scheme": "exact", + "network": "eip155:84532", + "asset": "erc20:0x...", + "amount": "1000000", + "payTo": "0x...", + "extra": { ... } + } + } + ``` +- **Success Response (200)**: + ```json + { + "isValid": true, + "payer": "0x..." + } + ``` +- **Invalid Response (200)**: + ```json + { + "isValid": false, + "invalidReason": "Invalid signature", + "payer": "0x..." + } + ``` + +### POST /settle +- **Purpose**: Settle a payment on-chain +- **Request Body**: Same as /verify +- **Success Response (200)**: + ```json + { + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x..." + } + ``` +- **Failure Response (200)**: + ```json + { + "success": false, + "errorReason": "Settlement failed", + "network": "eip155:84532" + } + ``` + +### GET /supported +- **Purpose**: Get supported payment kinds and extensions +- **Response (200)**: + ```json + { + "kinds": [ + { + "x402Version": 2, + "scheme": "exact", + "network": "eip155:84532", + "extra": {} + } + ], + "extensions": ["bazaar"] + } + ``` + +### GET /discovery/resources +- **Purpose**: List all discovered resources from bazaar extensions +- **Query Parameters**: + - `limit` (optional): Maximum number of resources to return (default: 100) + - `offset` (optional): Offset for pagination (default: 0) +- **Response (200)**: + ```json + { + "x402Version": 1, + "items": [ + { + "resource": "https://api.example.com/endpoint", + "type": "http", + "x402Version": 2, + "accepts": [...], + "discoveryInfo": {...}, + "lastUpdated": "2024-01-01T00:00:00Z", + "metadata": {} + } + ], + "pagination": { + "limit": 100, + "offset": 0, + "total": 1 + } + } + ``` + +### GET /health +- **Purpose**: Health check endpoint +- **Response (200)**: + ```json + { + "status": "ok" + } + ``` + +### POST /close +- **Purpose**: Gracefully shut down the facilitator +- **Response**: Should terminate the process with exit code 0 + +## Startup Requirements +- Must log "Facilitator listening" when ready to accept requests +- Must handle graceful shutdown on SIGTERM/SIGINT +- Must validate required environment variables on startup diff --git a/e2e/facilitators/typescript/README.md b/e2e/facilitators/typescript/README.md new file mode 100644 index 000000000..c7064b9f3 --- /dev/null +++ b/e2e/facilitators/typescript/README.md @@ -0,0 +1,175 @@ +# E2E Test Facilitator: TypeScript + +This facilitator demonstrates and tests the TypeScript x402 facilitator implementation with both EVM and SVM payment verification and settlement. + +## What It Tests + +### Core Functionality +- ✅ **V2 Protocol** - Modern x402 facilitator protocol +- ✅ **V1 Protocol** - Legacy x402 facilitator protocol +- ✅ **Payment Verification** - Validates payment payloads off-chain +- ✅ **Payment Settlement** - Executes transactions on-chain +- ✅ **Multi-chain Support** - EVM and SVM mechanisms +- ✅ **HTTP API** - Express.js server exposing facilitator endpoints + +### Facilitator Endpoints +- ✅ `POST /verify` - Verifies payment payload validity +- ✅ `POST /settle` - Settles payment on blockchain +- ✅ `GET /supported` - Returns supported payment kinds +- ✅ **Extension Support** - Bazaar discovery extension + +## What It Demonstrates + +### Lifecycle Hooks Usage + +This e2e facilitator showcases **production-ready lifecycle hook patterns**: + +```typescript +const facilitator = new x402Facilitator() + .register("eip155:*", new ExactEvmFacilitator(evmSigner)) + .registerExtension(BAZAAR) + // Hook 1: Track verified payments + extract discovery info + .onAfterVerify(async (context) => { + if (context.result.isValid) { + const paymentHash = createPaymentHash(context.paymentPayload); + verifiedPayments.set(paymentHash, context.timestamp); + + // Catalog discovered resources + const discovered = extractDiscoveryInfo(context.paymentPayload, context.requirements); + if (discovered) { + bazaarCatalog.catalogResource(discovered); + } + } + }) + // Hook 2: Validate payment was verified before settlement + .onBeforeSettle(async (context) => { + const paymentHash = createPaymentHash(context.paymentPayload); + if (!verifiedPayments.has(paymentHash)) { + return { abort: true, reason: "Payment must be verified first" }; + } + + // Check timeout + const age = context.timestamp - verifiedPayments.get(paymentHash)!; + if (age > 5 * 60 * 1000) { + return { abort: true, reason: "Verification expired" }; + } + }) + // Hook 3: Clean up tracking after settlement + .onAfterSettle(async (context) => { + const paymentHash = createPaymentHash(context.paymentPayload); + verifiedPayments.delete(paymentHash); + }) + // Hook 4: Clean up on failure too + .onSettleFailure(async (context) => { + const paymentHash = createPaymentHash(context.paymentPayload); + verifiedPayments.delete(paymentHash); + }); +``` + + +### Facilitator Setup + +```typescript +import { x402Facilitator } from "@x402/core/facilitator"; +import { ExactEvmFacilitator } from "@x402/evm"; +import { ExactEvmFacilitatorV1, NETWORKS as EVM_NETWORKS } from "@x402/evm/v1"; +import { ExactSvmFacilitator } from "@x402/svm"; +import { ExactSvmFacilitatorV1, NETWORKS as SVM_NETWORKS } from "@x402/svm/v1"; + +// Create facilitator with bazaar extension +const facilitator = new x402Facilitator() + .registerExtension("bazaar"); + +// Register EVM V2 wildcard +facilitator.register( + "eip155:*", + new ExactEvmFacilitator(evmSigner) +); + +// Register all EVM V1 networks +EVM_NETWORKS.forEach(network => { + facilitator.registerSchemeV1( + network, + new ExactEvmFacilitatorV1(evmSigner) + ); +}); + +// Register SVM schemes similarly... +``` + +### HTTP Server + +```typescript +import express from "express"; +import { createFacilitatorRouter } from "@x402/server/facilitator"; + +const app = express(); +app.use(express.json()); + +// Mount facilitator routes at root +app.use("/", createFacilitatorRouter(facilitator)); + +app.listen(port, () => { + console.log(`Facilitator ready at http://localhost:${port}`); +}); +``` + +### Key Concepts Shown + +1. **Extension Registration** - Bazaar discovery +2. **Comprehensive Network Support** - All EVM V1 networks, all SVM V1 networks +3. **Wildcard Schemes** - Efficient V2 registration with `eip155:*` and `solana:*` +4. **HTTP Router Integration** - `@x402/server/facilitator` for Express +5. **Real Signers** - Actual blockchain transaction submission +6. **Multi-Protocol** - V1 and V2 side-by-side + +## Test Scenarios + +This facilitator is tested with: +- **Clients:** TypeScript Fetch, Go HTTP +- **Servers:** Express (TypeScript), Gin (Go) +- **Networks:** Base Sepolia (EVM), Solana Devnet (SVM) +- **Test Cases:** + - V1 EVM payments + - V2 EVM payments + - V1 SVM payments + - V2 SVM payments + +### Success Criteria +- ✅ Verification returns valid status +- ✅ Settlement returns transaction hash +- ✅ Supported endpoint lists all mechanisms +- ✅ Bazaar extension included + +## Running + +```bash +# Via e2e test suite +cd e2e +pnpm test --facilitator=typescript + +# Direct execution +cd e2e/facilitators/typescript +export EVM_PRIVATE_KEY="0x..." +export SVM_PRIVATE_KEY="..." +export PORT=4025 +pnpm start +``` + +## Environment Variables + +- `PORT` - HTTP server port +- `EVM_PRIVATE_KEY` - Ethereum private key (hex with 0x prefix) +- `SVM_PRIVATE_KEY` - Solana private key (base58 encoded) + +## Package Dependencies + +- `@x402/core` - Core facilitator +- `@x402/server` - Facilitator HTTP router +- `@x402/evm` - EVM facilitator (V2) +- `@x402/evm/v1` - EVM facilitator (V1) + NETWORKS +- `@x402/svm` - SVM facilitator (V2) +- `@x402/svm/v1` - SVM facilitator (V1) + NETWORKS +- `express` - HTTP server +- `viem` - Ethereum transactions +- `@solana/web3.js` - Solana transactions diff --git a/e2e/facilitators/typescript/bazaar.ts b/e2e/facilitators/typescript/bazaar.ts new file mode 100644 index 000000000..a09f29fcd --- /dev/null +++ b/e2e/facilitators/typescript/bazaar.ts @@ -0,0 +1,59 @@ +import type { DiscoveryInfo } from "@x402/extensions/bazaar"; +import type { PaymentRequirements } from "@x402/core/types"; + +export interface DiscoveredResource { + resource: string; + type: "http"; + x402Version: number; + accepts: PaymentRequirements[]; + discoveryInfo?: DiscoveryInfo; + lastUpdated: string; + metadata?: Record; +} + +export class BazaarCatalog { + private discoveredResources = new Map(); + + catalogResource( + resourceUrl: string, + method: string, + x402Version: number, + discoveryInfo: DiscoveryInfo, + paymentRequirements: PaymentRequirements, + ): void { + console.log(`📝 Discovered resource: ${resourceUrl}`); + console.log(` Method: ${method}`); + console.log(` x402 Version: ${x402Version}`); + + this.discoveredResources.set(resourceUrl, { + resource: resourceUrl, + type: "http", + x402Version, + accepts: [paymentRequirements], + discoveryInfo, + lastUpdated: new Date().toISOString(), + metadata: {}, + }); + } + + getResources(limit: number = 100, offset: number = 0) { + const allResources = Array.from(this.discoveredResources.values()); + const total = allResources.length; + const items = allResources.slice(offset, offset + limit); + + return { + x402Version: 1, + items, + pagination: { + limit, + offset, + total, + }, + }; + } + + getCount(): number { + return this.discoveredResources.size; + } +} + diff --git a/e2e/facilitators/typescript/build.sh b/e2e/facilitators/typescript/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/facilitators/typescript/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/facilitators/typescript/index.ts b/e2e/facilitators/typescript/index.ts new file mode 100644 index 000000000..496c253e3 --- /dev/null +++ b/e2e/facilitators/typescript/index.ts @@ -0,0 +1,359 @@ +/** + * TypeScript Facilitator for E2E Testing + * + * This facilitator provides HTTP endpoints for payment verification and settlement + * using the x402 TypeScript SDK. + * + * Features: + * - Payment verification and settlement + * - Bazaar discovery extension support + * - Verified payment tracking (verify → settle flow) + * - Discovery resource cataloging + */ + +import { base58 } from "@scure/base"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { x402Facilitator } from "@x402/core/facilitator"; +import { + Network, + PaymentPayload, + PaymentRequirements, + SettleResponse, + VerifyResponse, +} from "@x402/core/types"; +import { toFacilitatorEvmSigner } from "@x402/evm"; +import { registerExactEvmScheme } from "@x402/evm/exact/facilitator"; +import { BAZAAR, extractDiscoveryInfo } from "@x402/extensions/bazaar"; +import { toFacilitatorSvmSigner } from "@x402/svm"; +import { registerExactSvmScheme } from "@x402/svm/exact/facilitator"; +import crypto from "crypto"; +import dotenv from "dotenv"; +import express from "express"; +import { createWalletClient, http, publicActions } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { baseSepolia } from "viem/chains"; +import { BazaarCatalog } from "./bazaar.js"; + +dotenv.config(); + +// Configuration +const PORT = process.env.PORT || "4022"; + +// Validate required environment variables +if (!process.env.EVM_PRIVATE_KEY) { + console.error("❌ EVM_PRIVATE_KEY environment variable is required"); + process.exit(1); +} + +if (!process.env.SVM_PRIVATE_KEY) { + console.error("❌ SVM_PRIVATE_KEY environment variable is required"); + process.exit(1); +} + +// Initialize the EVM account from private key +const evmAccount = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); +console.info(`EVM Facilitator account: ${evmAccount.address}`); + + +// Initialize the EVM account from private key +const svmAccount = await createKeyPairSignerFromBytes(base58.decode(process.env.SVM_PRIVATE_KEY as string)); +console.info(`EVM Facilitator account: ${evmAccount.address}`); + +// Create a Viem client with both wallet and public capabilities +const viemClient = createWalletClient({ + account: evmAccount, + chain: baseSepolia, + transport: http(), +}).extend(publicActions); + +// Initialize the x402 Facilitator with EVM and SVM support + +const evmSigner = toFacilitatorEvmSigner({ + address: evmAccount.address, + readContract: (args: { + address: `0x${string}`; + abi: readonly unknown[]; + functionName: string; + args?: readonly unknown[]; + }) => + viemClient.readContract({ + ...args, + args: args.args || [], + }), + verifyTypedData: (args: { + address: `0x${string}`; + domain: Record; + types: Record; + primaryType: string; + message: Record; + signature: `0x${string}`; + }) => viemClient.verifyTypedData(args as any), + writeContract: (args: { + address: `0x${string}`; + abi: readonly unknown[]; + functionName: string; + args: readonly unknown[]; + }) => + viemClient.writeContract({ + ...args, + args: args.args || [], + }), + sendTransaction: (args: { to: `0x${string}`; data: `0x${string}` }) => + viemClient.sendTransaction(args), + waitForTransactionReceipt: (args: { hash: `0x${string}` }) => + viemClient.waitForTransactionReceipt(args), + getCode: (args: { address: `0x${string}` }) => viemClient.getCode(args), +}); + +// Facilitator can now handle all Solana networks with automatic RPC creation +const svmSigner = toFacilitatorSvmSigner(svmAccount); + +const verifiedPayments = new Map(); +const bazaarCatalog = new BazaarCatalog(); + +function createPaymentHash(paymentPayload: PaymentPayload): string { + return crypto + .createHash("sha256") + .update(JSON.stringify(paymentPayload)) + .digest("hex"); +} + +const facilitator = new x402Facilitator(); + +// Register EVM and SVM schemes using the new register helpers +registerExactEvmScheme(facilitator, { + signer: evmSigner, + networks: "eip155:84532" // Base Sepolia +}); +registerExactSvmScheme(facilitator, { + signer: svmSigner, + networks: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" // Devnet +}); + +facilitator.registerExtension(BAZAAR) + // Lifecycle hooks for payment tracking and discovery + .onAfterVerify(async (context) => { + // Hook 1: Track verified payment for verify→settle flow validation + if (context.result.isValid) { + const paymentHash = createPaymentHash(context.paymentPayload); + verifiedPayments.set(paymentHash, Date.now()); + + // Hook 2: Extract and catalog bazaar discovery info + const discovered = extractDiscoveryInfo(context.paymentPayload, context.requirements); + if (discovered) { + bazaarCatalog.catalogResource( + discovered.resourceUrl, + discovered.method, + discovered.x402Version, + discovered.discoveryInfo, + context.requirements, + ); + console.log(`📦 Discovered resource: ${discovered.method} ${discovered.resourceUrl}`); + } + } + }) + .onBeforeSettle(async (context) => { + // Hook 3: Validate payment was previously verified + const paymentHash = createPaymentHash(context.paymentPayload); + const verificationTimestamp = verifiedPayments.get(paymentHash); + + if (!verificationTimestamp) { + return { + abort: true, + reason: "Payment must be verified before settlement", + }; + } + + // Check verification isn't too old (5 minute timeout) + const age = Date.now() - verificationTimestamp; + if (age > 5 * 60 * 1000) { + verifiedPayments.delete(paymentHash); + return { + abort: true, + reason: "Payment verification expired (must settle within 5 minutes)", + }; + } + }) + .onAfterSettle(async (context) => { + // Hook 4: Clean up verified payment tracking after settlement + const paymentHash = createPaymentHash(context.paymentPayload); + verifiedPayments.delete(paymentHash); + + if (context.result.success) { + console.log(`✅ Settlement completed: ${context.result.transaction}`); + } + }) + .onSettleFailure(async (context) => { + // Hook 5: Clean up on settlement failure too + const paymentHash = createPaymentHash(context.paymentPayload); + verifiedPayments.delete(paymentHash); + + console.error(`❌ Settlement failed: ${context.error.message}`); + }); + +// Initialize Express app +const app = express(); +app.use(express.json()); + +/** + * POST /verify + * Verify a payment against requirements + * + * Note: Payment tracking and bazaar discovery are handled by lifecycle hooks + */ +app.post("/verify", async (req, res) => { + try { + const { paymentPayload, paymentRequirements } = req.body as { paymentPayload: PaymentPayload; paymentRequirements: PaymentRequirements }; + + if (!paymentPayload || !paymentRequirements) { + return res.status(400).json({ + error: "Missing paymentPayload or paymentRequirements", + }); + } + + // Hooks will automatically: + // - Track verified payment (onAfterVerify) + // - Extract and catalog discovery info (onAfterVerify) + const response: VerifyResponse = await facilitator.verify( + paymentPayload, + paymentRequirements, + ); + + res.json(response); + } catch (error) { + console.error("Verify error:", error); + res.status(500).json({ + error: error instanceof Error ? error.message : "Unknown error", + }); + } +}); + +/** + * POST /settle + * Settle a payment on-chain + * + * Note: Verification validation and cleanup are handled by lifecycle hooks + */ +app.post("/settle", async (req, res) => { + try { + const { paymentPayload, paymentRequirements } = req.body; + + if (!paymentPayload || !paymentRequirements) { + return res.status(400).json({ + error: "Missing paymentPayload or paymentRequirements", + }); + } + + // Hooks will automatically: + // - Validate payment was verified (onBeforeSettle - will abort if not) + // - Check verification timeout (onBeforeSettle) + // - Clean up tracking (onAfterSettle / onSettleFailure) + const response: SettleResponse = await facilitator.settle( + paymentPayload as PaymentPayload, + paymentRequirements as PaymentRequirements, + ); + + res.json(response); + } catch (error) { + console.error("Settle error:", error); + + // Check if this was an abort from hook + if (error instanceof Error && error.message.includes("Settlement aborted:")) { + // Return a proper SettleResponse instead of 500 error + return res.json({ + success: false, + errorReason: error.message.replace("Settlement aborted: ", ""), + network: req.body?.paymentPayload?.network || "unknown", + } as SettleResponse); + } + + res.status(500).json({ + error: error instanceof Error ? error.message : "Unknown error", + }); + } +}); + +/** + * GET /supported + * Get supported payment kinds and extensions + */ +app.get("/supported", async (req, res) => { + try { + const response = facilitator.getSupported(); + res.json(response); + } catch (error) { + console.error("Supported error:", error); + res.status(500).json({ + error: error instanceof Error ? error.message : "Unknown error", + }); + } +}); + +app.get("/discovery/resources", (req, res) => { + try { + const limit = parseInt(req.query.limit as string) || 100; + const offset = parseInt(req.query.offset as string) || 0; + + const response = bazaarCatalog.getResources(limit, offset); + res.json(response); + } catch (error) { + console.error("Discovery resources error:", error); + res.status(500).json({ + error: error instanceof Error ? error.message : "Unknown error", + }); + } +}); + +/** + * GET /health + * Health check endpoint + */ +app.get("/health", (req, res) => { + res.json({ + status: "ok", + network: "eip155:84532", + facilitator: "typescript", + version: "2.0.0", + extensions: [BAZAAR], + discoveredResources: bazaarCatalog.getCount(), + }); +}); + +/** + * POST /close + * Graceful shutdown endpoint + */ +app.post("/close", (req, res) => { + res.json({ message: "Facilitator shutting down gracefully" }); + console.log("Received shutdown request"); + + // Give time for response to be sent + setTimeout(() => { + process.exit(0); + }, 100); +}); + +// Start the server +app.listen(parseInt(PORT), () => { + console.log(` +╔════════════════════════════════════════════════════════╗ +║ x402 TypeScript Facilitator ║ +╠════════════════════════════════════════════════════════╣ +║ Server: http://localhost:${PORT} ║ +║ Network: eip155:84532 ║ +║ Address: ${evmAccount.address} ║ +║ Extensions: bazaar ║ +║ ║ +║ Endpoints: ║ +║ • POST /verify (verify payment) ║ +║ • POST /settle (settle payment) ║ +║ • GET /supported (get supported kinds) ║ +║ • GET /discovery/resources (list discovered) ║ +║ • GET /health (health check) ║ +║ • POST /close (shutdown server) ║ +╚════════════════════════════════════════════════════════╝ + `); + + // Log that facilitator is ready (needed for e2e test discovery) + console.log("Facilitator listening"); +}); diff --git a/e2e/facilitators/typescript/install.sh b/e2e/facilitators/typescript/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/facilitators/typescript/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/facilitators/typescript/package.json b/e2e/facilitators/typescript/package.json new file mode 100644 index 000000000..55aad202b --- /dev/null +++ b/e2e/facilitators/typescript/package.json @@ -0,0 +1,33 @@ +{ + "name": "@x402/e2e-facilitator-typescript", + "version": "2.0.0", + "type": "module", + "private": true, + "scripts": { + "start": "tsx index.ts", + "dev": "tsx watch index.ts", + "build": "tsc", + "lint": "eslint .", + "format": "prettier --write .", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@scure/base": "^1.2.6", + "@solana/kit": "^2.1.1", + "@x402/core": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/extensions": "workspace:*", + "@x402/svm": "workspace:*", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "viem": "^2.21.54" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/node": "^22.10.1", + "eslint": "^9.15.0", + "prettier": "^3.3.3", + "tsx": "^4.19.2", + "typescript": "^5.7.2" + } +} \ No newline at end of file diff --git a/e2e/facilitators/typescript/run.sh b/e2e/facilitators/typescript/run.sh new file mode 100755 index 000000000..2864b3a7e --- /dev/null +++ b/e2e/facilitators/typescript/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pnpm start diff --git a/e2e/facilitators/typescript/test.config.json b/e2e/facilitators/typescript/test.config.json new file mode 100644 index 000000000..b4a4abc21 --- /dev/null +++ b/e2e/facilitators/typescript/test.config.json @@ -0,0 +1,27 @@ +{ + "name": "typescript", + "type": "facilitator", + "language": "typescript", + "protocolFamilies": [ + "evm", + "svm" + ], + "x402Versions": [ + 1, + 2 + ], + "extensions": [ + "bazaar" + ], + "environment": { + "required": [ + "PORT", + "EVM_PRIVATE_KEY", + "SVM_PRIVATE_KEY" + ], + "optional": [ + "EVM_NETWORK", + "SVM_NETWORK" + ] + } +} \ No newline at end of file diff --git a/e2e/facilitators/typescript/tsconfig.json b/e2e/facilitators/typescript/tsconfig.json new file mode 100644 index 000000000..e85a5d7c2 --- /dev/null +++ b/e2e/facilitators/typescript/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "lib": [ + "ES2022" + ], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "./dist" + }, + "include": [ + "*.ts" + ], + "exclude": [ + "node_modules", + "dist" + ] +} \ No newline at end of file diff --git a/e2e/legacy/clients/axios/.env-local b/e2e/legacy/clients/axios/.env-local new file mode 100644 index 000000000..571d0bcf6 --- /dev/null +++ b/e2e/legacy/clients/axios/.env-local @@ -0,0 +1,4 @@ +RESOURCE_SERVER_URL=http://localhost:4021 +ENDPOINT_PATH=/weather +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= diff --git a/examples/typescript/agent/.prettierignore b/e2e/legacy/clients/axios/.prettierignore similarity index 100% rename from examples/typescript/agent/.prettierignore rename to e2e/legacy/clients/axios/.prettierignore diff --git a/examples/typescript/agent/.prettierrc b/e2e/legacy/clients/axios/.prettierrc similarity index 100% rename from examples/typescript/agent/.prettierrc rename to e2e/legacy/clients/axios/.prettierrc diff --git a/e2e/legacy/clients/axios/README.md b/e2e/legacy/clients/axios/README.md new file mode 100644 index 000000000..4bb308ba9 --- /dev/null +++ b/e2e/legacy/clients/axios/README.md @@ -0,0 +1,80 @@ +# x402-axios Example Client + +This is an example client that demonstrates how to use the `x402-axios` package to make HTTP requests to endpoints protected by the x402 payment protocol. + +## Prerequisites + +- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) +- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) +- A running x402 server (you can use the example express server at `examples/typescript/servers/express`) +- A valid Ethereum private key for making payments + +## Setup + +1. Install and build all packages from the typescript examples root: +```bash +cd ../../ +pnpm install +pnpm build +cd clients/axios +``` + +2. Copy `.env-local` to `.env` and add your Ethereum private key (remember it should have USDC on Base Sepolia, which you can provision using the [CDP Faucet](https://portal.cdp.coinbase.com/products/faucet)): +```bash +cp .env-local .env +``` + +3. Start the example client (remember you need to be running a server locally or point at an endpoint): +```bash +pnpm dev +``` + +## How It Works + +The example demonstrates how to: +1. Create a wallet client using viem +2. Create an Axios instance with x402 payment handling +3. Make a request to a paid endpoint +4. Handle the response or any errors + +## Example Code + +```typescript +import { config } from "dotenv"; +import { createWalletClient, http, publicActions } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { withPaymentInterceptor } from "x402-axios"; +import axios from "axios"; +import { baseSepolia } from "viem/chains"; + +config(); + +const { RESOURCE_SERVER_URL, PRIVATE_KEY, ENDPOINT_PATH } = process.env; + +// Create wallet client +const account = privateKeyToAccount(PRIVATE_KEY as "0x${string}"); +const client = createWalletClient({ + account, + transport: http(), + chain: baseSepolia, +}).extend(publicActions); + +// Create Axios instance with payment handling +const api = withPaymentInterceptor( + axios.create({ + baseURL: RESOURCE_SERVER_URL, + }), + client +); + +// Make request to paid endpoint +api + .get(ENDPOINT_PATH) + .then(response => { + console.log(response.headers); + console.log(response.data); + }) + .catch(error => { + console.error(error.response?.data?.error); + }); +``` diff --git a/e2e/legacy/clients/axios/build.sh b/e2e/legacy/clients/axios/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/legacy/clients/axios/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/examples/typescript/agent/eslint.config.js b/e2e/legacy/clients/axios/eslint.config.js similarity index 100% rename from examples/typescript/agent/eslint.config.js rename to e2e/legacy/clients/axios/eslint.config.js diff --git a/e2e/legacy/clients/axios/index.ts b/e2e/legacy/clients/axios/index.ts new file mode 100644 index 000000000..c0b17553b --- /dev/null +++ b/e2e/legacy/clients/axios/index.ts @@ -0,0 +1,58 @@ +import axios from "axios"; +import { config } from "dotenv"; +import { Hex } from "viem"; +import { withPaymentInterceptor, decodeXPaymentResponse, createSigner, MultiNetworkSigner } from "x402-axios"; + +config(); + +const evmPrivateKey = process.env.EVM_PRIVATE_KEY as Hex; +const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string; +const baseURL = process.env.RESOURCE_SERVER_URL as string; // e.g. https://example.com +const endpointPath = process.env.ENDPOINT_PATH as string; // e.g. /weather + +if (!baseURL || !evmPrivateKey || !svmPrivateKey || !endpointPath) { + console.error("Missing required environment variables"); + process.exit(1); +} + +const evmSigner = await createSigner("base-sepolia", evmPrivateKey); +const svmSigner = await createSigner("solana-devnet", svmPrivateKey); +const account = { evm: evmSigner, svm: svmSigner } as MultiNetworkSigner; + +const api = withPaymentInterceptor( + axios.create({ + baseURL, + }), + account, +); + +api + .get(endpointPath) + .then(response => { + console.log("Response received:", { + status: response.status, + headers: response.headers, + data: response.data + }); + + const result = { + success: true, + data: response.data, + status_code: response.status, + payment_response: decodeXPaymentResponse(response.headers["x-payment-response"]) + }; + + // Output structured result as JSON for proxy to parse + console.log(JSON.stringify(result)); + process.exit(0); + }) + .catch(error => { + const errorResult = { + success: false, + error: error.message || String(error), + status_code: error.response?.status + }; + + console.log(JSON.stringify(errorResult)); + process.exit(1); + }); diff --git a/e2e/legacy/clients/axios/install.sh b/e2e/legacy/clients/axios/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/legacy/clients/axios/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/legacy/clients/axios/package.json b/e2e/legacy/clients/axios/package.json new file mode 100644 index 000000000..0d50932e7 --- /dev/null +++ b/e2e/legacy/clients/axios/package.json @@ -0,0 +1,30 @@ +{ + "name": "axios-e2e", + "private": true, + "type": "module", + "scripts": { + "dev": "tsx index.ts", + "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", + "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", + "lint": "eslint . --ext .ts --fix", + "lint:check": "eslint . --ext .ts" + }, + "dependencies": { + "axios": "^1.7.9", + "dotenv": "^16.5.0", + "viem": "^2.21.26", + "x402-axios": "workspace:*" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "eslint": "^9.24.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", + "prettier": "3.5.2", + "tsx": "^4.7.0", + "typescript": "^5.3.0" + } +} \ No newline at end of file diff --git a/e2e/legacy/clients/axios/run.sh b/e2e/legacy/clients/axios/run.sh new file mode 100755 index 000000000..aa2c67d61 --- /dev/null +++ b/e2e/legacy/clients/axios/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pnpm dev \ No newline at end of file diff --git a/e2e/legacy/clients/axios/test.config.json b/e2e/legacy/clients/axios/test.config.json new file mode 100644 index 000000000..06c16dad4 --- /dev/null +++ b/e2e/legacy/clients/axios/test.config.json @@ -0,0 +1,21 @@ +{ + "name": "axios", + "type": "client", + "language": "typescript", + "protocolFamilies": [ + "evm", + "svm" + ], + "x402Versions": [ + 1 + ], + "environment": { + "required": [ + "EVM_PRIVATE_KEY", + "SVM_PRIVATE_KEY", + "RESOURCE_SERVER_URL", + "ENDPOINT_PATH" + ], + "optional": [] + } +} \ No newline at end of file diff --git a/e2e/legacy/clients/axios/tsconfig.json b/e2e/legacy/clients/axios/tsconfig.json new file mode 100644 index 000000000..81e0e7f1f --- /dev/null +++ b/e2e/legacy/clients/axios/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "strict": true, + "resolveJsonModule": true, + "baseUrl": ".", + "types": [ + "node" + ] + }, + "include": [ + "index.ts" + ] +} \ No newline at end of file diff --git a/e2e/legacy/clients/fetch/.env-local b/e2e/legacy/clients/fetch/.env-local new file mode 100644 index 000000000..571d0bcf6 --- /dev/null +++ b/e2e/legacy/clients/fetch/.env-local @@ -0,0 +1,4 @@ +RESOURCE_SERVER_URL=http://localhost:4021 +ENDPOINT_PATH=/weather +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= diff --git a/examples/typescript/clients/cdp-sdk/.prettierignore b/e2e/legacy/clients/fetch/.prettierignore similarity index 100% rename from examples/typescript/clients/cdp-sdk/.prettierignore rename to e2e/legacy/clients/fetch/.prettierignore diff --git a/examples/typescript/clients/cdp-sdk/.prettierrc b/e2e/legacy/clients/fetch/.prettierrc similarity index 100% rename from examples/typescript/clients/cdp-sdk/.prettierrc rename to e2e/legacy/clients/fetch/.prettierrc diff --git a/e2e/legacy/clients/fetch/README.md b/e2e/legacy/clients/fetch/README.md new file mode 100644 index 000000000..f04ed5516 --- /dev/null +++ b/e2e/legacy/clients/fetch/README.md @@ -0,0 +1,75 @@ +# x402-fetch Example Client + +This is an example client that demonstrates how to use the `x402-fetch` package to make HTTP requests to endpoints protected by the x402 payment protocol. + +## Prerequisites + +- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) +- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) +- A running x402 server (you can use the example express server at `examples/typescript/servers/express`) +- A valid Ethereum private key for making payments + +## Setup + +1. Install and build all packages from the typescript examples root: +```bash +cd ../../ +pnpm install +pnpm build +cd clients/fetch +``` + +2. Copy `.env-local` to `.env` and add your Ethereum private key: +```bash +cp .env-local .env +``` + +3. Start the example client: +```bash +pnpm dev +``` + +## How It Works + +The example demonstrates how to: +1. Create a wallet client using viem +2. Wrap the native fetch function with x402 payment handling +3. Make a request to a paid endpoint +4. Handle the response or any errors + +## Example Code + +```typescript +import { config } from "dotenv"; +import { createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { wrapFetchWithPayment } from "x402-fetch"; +import { baseSepolia } from "viem/chains"; + +config(); + +const { RESOURCE_SERVER_URL, PRIVATE_KEY, ENDPOINT_PATH } = process.env; + +// Create wallet client +const account = privateKeyToAccount(PRIVATE_KEY as `0x${string}`); +const client = createWalletClient({ + account, + transport: http(), + chain: baseSepolia, +}); + +// Wrap fetch with payment handling +const fetchWithPay = wrapFetchWithPayment(fetch, client); + +// Make request to paid endpoint +fetchWithPay(`${RESOURCE_SERVER_URL}${ENDPOINT_PATH}`, { + method: "GET", +}) + .then(async response => { + const body = await response.json(); + console.log(body); + }) + .catch(error => { + console.error(error.response?.data?.error); + }); +``` diff --git a/e2e/legacy/clients/fetch/build.sh b/e2e/legacy/clients/fetch/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/legacy/clients/fetch/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/examples/typescript/clients/cdp-sdk/eslint.config.js b/e2e/legacy/clients/fetch/eslint.config.js similarity index 100% rename from examples/typescript/clients/cdp-sdk/eslint.config.js rename to e2e/legacy/clients/fetch/eslint.config.js diff --git a/e2e/legacy/clients/fetch/index.ts b/e2e/legacy/clients/fetch/index.ts new file mode 100644 index 000000000..e7625705a --- /dev/null +++ b/e2e/legacy/clients/fetch/index.ts @@ -0,0 +1,51 @@ +import { config } from "dotenv"; +import { Hex } from "viem"; +import { createSigner, decodeXPaymentResponse, MultiNetworkSigner, wrapFetchWithPayment } from "x402-fetch"; + +config(); + +const evmPrivateKey = process.env.EVM_PRIVATE_KEY as Hex; +const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string; +const baseURL = process.env.RESOURCE_SERVER_URL as string; +const endpointPath = process.env.ENDPOINT_PATH as string; +const url = `${baseURL}${endpointPath}`; + +if (!baseURL || !evmPrivateKey || !svmPrivateKey || !endpointPath) { + console.error("Missing required environment variables"); + process.exit(1); +} + +const evmSigner = await createSigner("base-sepolia", evmPrivateKey); +const svmSigner = await createSigner("solana-devnet", svmPrivateKey); +const account = { evm: evmSigner, svm: svmSigner } as MultiNetworkSigner; + +const fetchWithPayment = wrapFetchWithPayment(fetch, account); + +fetchWithPayment(url, { + method: "GET", +}) + .then(async response => { + const data = await response.json(); + const paymentResponse = response.headers.get("x-payment-response"); + + const result = { + success: true, + data: data, + status_code: response.status, + payment_response: decodeXPaymentResponse(paymentResponse!) + }; + + // Output structured result as JSON for proxy to parse + console.log(JSON.stringify(result)); + process.exit(0); + }) + .catch(error => { + const errorResult = { + success: false, + error: error.message || String(error), + status_code: error.response?.status + }; + + console.log(JSON.stringify(errorResult)); + process.exit(1); + }); diff --git a/e2e/legacy/clients/fetch/install.sh b/e2e/legacy/clients/fetch/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/legacy/clients/fetch/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/examples/typescript/discovery/package.json b/e2e/legacy/clients/fetch/package.json similarity index 88% rename from examples/typescript/discovery/package.json rename to e2e/legacy/clients/fetch/package.json index 9308c71f7..f079ea58f 100644 --- a/examples/typescript/discovery/package.json +++ b/e2e/legacy/clients/fetch/package.json @@ -1,5 +1,5 @@ { - "name": "client-discovery-example", + "name": "fetch-client-example", "private": true, "type": "module", "scripts": { @@ -11,18 +11,18 @@ }, "dependencies": { "axios": "^1.7.9", + "dotenv": "^16.4.7", "viem": "^2.21.26", - "x402": "workspace:*", - "@coinbase/x402": "workspace:*" + "x402-fetch": "workspace:*" }, "devDependencies": { "@eslint/js": "^9.24.0", - "@typescript-eslint/eslint-plugin": "^8.29.1", - "@typescript-eslint/parser": "^8.29.1", "eslint": "^9.24.0", - "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsdoc": "^50.6.9", "eslint-plugin-prettier": "^5.2.6", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "eslint-plugin-import": "^2.31.0", "prettier": "3.5.2", "tsx": "^4.7.0", "typescript": "^5.3.0" diff --git a/e2e/legacy/clients/fetch/run.sh b/e2e/legacy/clients/fetch/run.sh new file mode 100755 index 000000000..aa2c67d61 --- /dev/null +++ b/e2e/legacy/clients/fetch/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pnpm dev \ No newline at end of file diff --git a/e2e/legacy/clients/fetch/test.config.json b/e2e/legacy/clients/fetch/test.config.json new file mode 100644 index 000000000..792d2c146 --- /dev/null +++ b/e2e/legacy/clients/fetch/test.config.json @@ -0,0 +1,21 @@ +{ + "name": "fetch", + "type": "client", + "language": "typescript", + "protocolFamilies": [ + "evm", + "svm" + ], + "x402Versions": [ + 1 + ], + "environment": { + "required": [ + "EVM_PRIVATE_KEY", + "SVM_PRIVATE_KEY", + "RESOURCE_SERVER_URL", + "ENDPOINT_PATH" + ], + "optional": [] + } +} \ No newline at end of file diff --git a/e2e/legacy/clients/fetch/tsconfig.json b/e2e/legacy/clients/fetch/tsconfig.json new file mode 100644 index 000000000..81e0e7f1f --- /dev/null +++ b/e2e/legacy/clients/fetch/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "strict": true, + "resolveJsonModule": true, + "baseUrl": ".", + "types": [ + "node" + ] + }, + "include": [ + "index.ts" + ] +} \ No newline at end of file diff --git a/e2e/legacy/clients/httpx/build.sh b/e2e/legacy/clients/httpx/build.sh new file mode 100755 index 000000000..f5fbe5e8f --- /dev/null +++ b/e2e/legacy/clients/httpx/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# Python doesn't require a build step +# This file is intentionally empty +exit 0 + diff --git a/e2e/legacy/clients/httpx/install.sh b/e2e/legacy/clients/httpx/install.sh new file mode 100755 index 000000000..e50310977 --- /dev/null +++ b/e2e/legacy/clients/httpx/install.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Installing Python dependencies for httpx client..." +uv sync +echo "✅ Dependencies installed" + diff --git a/e2e/clients/httpx/main.py b/e2e/legacy/clients/httpx/main.py similarity index 88% rename from e2e/clients/httpx/main.py rename to e2e/legacy/clients/httpx/main.py index c5dbe726d..2ee38cd15 100644 --- a/e2e/clients/httpx/main.py +++ b/e2e/legacy/clients/httpx/main.py @@ -25,8 +25,10 @@ async def main(): - # Create httpx client with x402 payment hooks - async with httpx.AsyncClient(base_url=base_url) as client: + # Create httpx client with x402 payment hooks and increased timeout + # Set timeout to 30 seconds to handle busy servers during test runs + timeout = httpx.Timeout(30.0, connect=10.0) + async with httpx.AsyncClient(base_url=base_url, timeout=timeout) as client: # Add payment hooks directly to client.event_hooks client.event_hooks = x402_payment_hooks(account) diff --git a/e2e/clients/httpx/pyproject.toml b/e2e/legacy/clients/httpx/pyproject.toml similarity index 88% rename from e2e/clients/httpx/pyproject.toml rename to e2e/legacy/clients/httpx/pyproject.toml index 6485e2902..0e68fc429 100644 --- a/e2e/clients/httpx/pyproject.toml +++ b/e2e/legacy/clients/httpx/pyproject.toml @@ -24,4 +24,4 @@ allow-direct-references = true package = false [tool.uv.sources] -x402 = { path = "../../../python/x402", editable = true } \ No newline at end of file +x402 = { path = "../../../../python/x402", editable = true } \ No newline at end of file diff --git a/e2e/clients/httpx/run.sh b/e2e/legacy/clients/httpx/run.sh similarity index 100% rename from e2e/clients/httpx/run.sh rename to e2e/legacy/clients/httpx/run.sh diff --git a/e2e/clients/httpx/test.config.json b/e2e/legacy/clients/httpx/test.config.json similarity index 90% rename from e2e/clients/httpx/test.config.json rename to e2e/legacy/clients/httpx/test.config.json index 0a5616452..736aaaf42 100644 --- a/e2e/clients/httpx/test.config.json +++ b/e2e/legacy/clients/httpx/test.config.json @@ -5,6 +5,9 @@ "protocolFamilies": [ "evm" ], + "x402Versions": [ + 1 + ], "description": "Python httpx client with x402 payment hooks", "environment": { "required": [ diff --git a/e2e/clients/httpx/uv.lock b/e2e/legacy/clients/httpx/uv.lock similarity index 99% rename from e2e/clients/httpx/uv.lock rename to e2e/legacy/clients/httpx/uv.lock index 32867d5c5..f2124e12d 100644 --- a/e2e/clients/httpx/uv.lock +++ b/e2e/legacy/clients/httpx/uv.lock @@ -1863,7 +1863,7 @@ wheels = [ [[package]] name = "x402" version = "0.2.1" -source = { editable = "../../../python/x402" } +source = { editable = "../../../../python/x402" } dependencies = [ { name = "eth-account" }, { name = "eth-typing" }, @@ -1912,7 +1912,7 @@ requires-dist = [ { name = "eth-account", specifier = ">=0.8.0" }, { name = "httpx", specifier = ">=0.24.0" }, { name = "python-dotenv", specifier = ">=1.0.0" }, - { name = "x402", editable = "../../../python/x402" }, + { name = "x402", editable = "../../../../python/x402" }, ] [[package]] diff --git a/e2e/legacy/clients/requests/build.sh b/e2e/legacy/clients/requests/build.sh new file mode 100755 index 000000000..f5fbe5e8f --- /dev/null +++ b/e2e/legacy/clients/requests/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# Python doesn't require a build step +# This file is intentionally empty +exit 0 + diff --git a/e2e/legacy/clients/requests/install.sh b/e2e/legacy/clients/requests/install.sh new file mode 100755 index 000000000..f15714ef0 --- /dev/null +++ b/e2e/legacy/clients/requests/install.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Installing Python dependencies for requests client..." +uv sync +echo "✅ Dependencies installed" + diff --git a/e2e/clients/requests/main.py b/e2e/legacy/clients/requests/main.py similarity index 100% rename from e2e/clients/requests/main.py rename to e2e/legacy/clients/requests/main.py diff --git a/e2e/clients/requests/pyproject.toml b/e2e/legacy/clients/requests/pyproject.toml similarity index 88% rename from e2e/clients/requests/pyproject.toml rename to e2e/legacy/clients/requests/pyproject.toml index 37c46fedf..2e426f833 100644 --- a/e2e/clients/requests/pyproject.toml +++ b/e2e/legacy/clients/requests/pyproject.toml @@ -24,4 +24,4 @@ allow-direct-references = true package = false [tool.uv.sources] -x402 = { path = "../../../python/x402", editable = true } \ No newline at end of file +x402 = { path = "../../../../python/x402", editable = true } \ No newline at end of file diff --git a/e2e/clients/requests/run.sh b/e2e/legacy/clients/requests/run.sh similarity index 100% rename from e2e/clients/requests/run.sh rename to e2e/legacy/clients/requests/run.sh diff --git a/e2e/clients/requests/test.config.json b/e2e/legacy/clients/requests/test.config.json similarity index 91% rename from e2e/clients/requests/test.config.json rename to e2e/legacy/clients/requests/test.config.json index 4cd52ead5..53138f718 100644 --- a/e2e/clients/requests/test.config.json +++ b/e2e/legacy/clients/requests/test.config.json @@ -5,6 +5,9 @@ "protocolFamilies": [ "evm" ], + "x402Versions": [ + 1 + ], "description": "Python requests client with x402 HTTP adapter", "environment": { "required": [ diff --git a/e2e/clients/requests/uv.lock b/e2e/legacy/clients/requests/uv.lock similarity index 99% rename from e2e/clients/requests/uv.lock rename to e2e/legacy/clients/requests/uv.lock index d8dc6c899..39564a65f 100644 --- a/e2e/clients/requests/uv.lock +++ b/e2e/legacy/clients/requests/uv.lock @@ -1863,7 +1863,7 @@ wheels = [ [[package]] name = "x402" version = "0.2.1" -source = { editable = "../../../python/x402" } +source = { editable = "../../../../python/x402" } dependencies = [ { name = "eth-account" }, { name = "eth-typing" }, @@ -1912,7 +1912,7 @@ requires-dist = [ { name = "eth-account", specifier = ">=0.8.0" }, { name = "python-dotenv", specifier = ">=1.0.0" }, { name = "requests", specifier = ">=2.31.0" }, - { name = "x402", editable = "../../../python/x402" }, + { name = "x402", editable = "../../../../python/x402" }, ] [[package]] diff --git a/e2e/legacy/servers/express/.env-local b/e2e/legacy/servers/express/.env-local new file mode 100644 index 000000000..043fec0ae --- /dev/null +++ b/e2e/legacy/servers/express/.env-local @@ -0,0 +1,9 @@ +FACILITATOR_URL=https://x402.org/facilitator +EVM_NETWORK=base-sepolia +SVM_NETWORK=solana-devnet +EVM_ADDRESS= +SVM_ADDRESS= + +# required if using the Base mainnet facilitator +CDP_API_KEY_ID="Coinbase Developer Platform Key" +CDP_API_KEY_SECRET="Coinbase Developer Platform Key Secret" \ No newline at end of file diff --git a/examples/typescript/clients/chainlink-vrf-nft/.prettierignore b/e2e/legacy/servers/express/.prettierignore similarity index 100% rename from examples/typescript/clients/chainlink-vrf-nft/.prettierignore rename to e2e/legacy/servers/express/.prettierignore diff --git a/examples/typescript/clients/chainlink-vrf-nft/.prettierrc b/e2e/legacy/servers/express/.prettierrc similarity index 100% rename from examples/typescript/clients/chainlink-vrf-nft/.prettierrc rename to e2e/legacy/servers/express/.prettierrc diff --git a/e2e/legacy/servers/express/README.md b/e2e/legacy/servers/express/README.md new file mode 100644 index 000000000..5adab235c --- /dev/null +++ b/e2e/legacy/servers/express/README.md @@ -0,0 +1,146 @@ +# x402-express Example Server + +This is an example Express.js server that demonstrates how to use the `x402-express` middleware to implement paywall functionality in your API endpoints. + +## Prerequisites + +- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) +- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) +- A valid Ethereum address for receiving payments +- Coinbase Developer Platform API Key & Secret (if accepting payments on Base mainnet) + -- Get them here [https://portal.cdp.coinbase.com/projects](https://portal.cdp.coinbase.com/projects) + +## Setup + +1. Copy `.env-local` to `.env` and add your Ethereum address to receive payments: + +```bash +cp .env-local .env +``` + +2. Install and build all packages from the typescript examples root: +```bash +cd ../../ +pnpm install +pnpm build +cd servers/express +``` + +3. Run the server +```bash +pnpm install +pnpm dev +``` + +## Testing the Server + +You can test the server using one of the example clients: + +### Using the Fetch Client +```bash +cd ../clients/fetch +# Ensure .env is setup +pnpm install +pnpm dev +``` + +### Using the Axios Client +```bash +cd ../clients/axios +# Ensure .env is setup +pnpm install +pnpm dev +``` + +These clients will demonstrate how to: +1. Make an initial request to get payment requirements +2. Process the payment requirements +3. Make a second request with the payment token + +## Example Endpoint + +The server includes a single example endpoint at `/weather` that requires a payment of $0.001 to access. The endpoint returns a simple weather report. + +## Response Format + +### Payment Required (402) +```json +{ + "error": "X-PAYMENT header is required", + "paymentRequirements": { + "scheme": "exact", + "network": "base", + "maxAmountRequired": "1000", + "resource": "http://localhost:4021/weather", + "description": "", + "mimeType": "", + "payTo": "0xYourAddress", + "maxTimeoutSeconds": 60, + "asset": "0x...", + "outputSchema": null, + "extra": null + } +} +``` + +### Successful Response +```ts +// Body +{ + "report": { + "weather": "sunny", + "temperature": 70 + } +} +// Headers +{ + "X-PAYMENT-RESPONSE": "..." // Encoded response object +} +``` + +## Extending the Example + +To add more paid endpoints, follow this pattern: + +```typescript +// First, configure the payment middleware with your routes +app.use( + paymentMiddleware( + payTo, + { + // Define your routes and their payment requirements + "GET /your-endpoint": { + price: "$0.10", + network: "base-sepolia", + }, + "/premium/*": { + price: { + amount: "100000", + asset: { + address: "0xabc", + decimals: 18, + eip712: { + name: "WETH", + version: "1", + }, + }, + }, + network: "base-sepolia", + }, + }, + ), +); + +// Then define your routes as normal +app.get("/your-endpoint", (req, res) => { + res.json({ + // Your response data + }); +}); + +app.get("/premium/content", (req, res) => { + res.json({ + content: "This is premium content", + }); +}); +``` diff --git a/e2e/legacy/servers/express/build.sh b/e2e/legacy/servers/express/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/legacy/servers/express/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/examples/typescript/servers/mainnet/eslint.config.js b/e2e/legacy/servers/express/eslint.config.js similarity index 100% rename from examples/typescript/servers/mainnet/eslint.config.js rename to e2e/legacy/servers/express/eslint.config.js diff --git a/e2e/legacy/servers/express/index.ts b/e2e/legacy/servers/express/index.ts new file mode 100644 index 000000000..deabbe4eb --- /dev/null +++ b/e2e/legacy/servers/express/index.ts @@ -0,0 +1,84 @@ +import express from "express"; +import { Network, paymentMiddleware, SolanaAddress } from "x402-express"; +import dotenv from "dotenv"; + +dotenv.config(); + +const evmNetwork = process.env.EVM_NETWORK as Network; +const svmNetwork = process.env.SVM_NETWORK as Network; +const payToEvm = process.env.EVM_PAYEE_ADDRESS as `0x${string}`; +const payToSvm = process.env.SVM_PAYEE_ADDRESS as SolanaAddress; +const port = process.env.PORT || "4021"; +const facilitatorUrl = process.env.FACILITATOR_URL; + +if (!payToEvm || !evmNetwork) { + console.error("Missing required environment variables"); + process.exit(1); +} + +// Create facilitator config if URL is provided +const facilitatorConfig = facilitatorUrl + ? { url: facilitatorUrl as `${string}://${string}` } + : undefined as any; + +if (facilitatorUrl) { + console.log(`Using remote facilitator at: ${facilitatorUrl}`); +} else { + console.log(`Using default facilitator`); +} + +const app = express(); + +app.use( + paymentMiddleware( + payToEvm, + { + "GET /protected": { + price: "$0.001", + network: evmNetwork, + }, + }, + facilitatorConfig + ), +); + +app.use( + paymentMiddleware( + payToSvm, + { + "GET /protected-svm": { + price: "$0.001", + network: svmNetwork, + }, + }, + facilitatorConfig + ), +); + +app.get("/protected", (req, res) => { + res.json({ + message: "Protected endpoint accessed successfully", + timestamp: new Date().toISOString(), + }); +}); + +app.get("/protected-svm", (req, res) => { + res.json({ + message: "Protected endpoint #2 accessed successfully", + timestamp: new Date().toISOString(), + }); +}); + +app.get("/health", (req, res) => { + res.json({ status: "ok" }); +}); + +app.post("/close", (req, res) => { + res.json({ message: "Server shutting down" }); + console.log("Received shutdown request"); + process.exit(0); +}); + +app.listen(parseInt(port), () => { + console.log(`Server listening at http://localhost:${port}`); +}); \ No newline at end of file diff --git a/e2e/legacy/servers/express/install.sh b/e2e/legacy/servers/express/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/legacy/servers/express/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/legacy/servers/express/package.json b/e2e/legacy/servers/express/package.json new file mode 100644 index 000000000..514c25588 --- /dev/null +++ b/e2e/legacy/servers/express/package.json @@ -0,0 +1,31 @@ +{ + "name": "express-e2e", + "private": true, + "type": "module", + "scripts": { + "dev": "tsx index.ts", + "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", + "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", + "lint": "eslint . --ext .ts --fix", + "lint:check": "eslint . --ext .ts" + }, + "dependencies": { + "dotenv": "^16.6.1", + "express": "^4.18.2", + "x402-express": "workspace:*" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@types/express": "^5.0.1", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "eslint": "^9.24.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", + "prettier": "3.5.2", + "tsup": "^7.2.0", + "tsx": "^4.7.0", + "typescript": "^5.3.0" + } +} \ No newline at end of file diff --git a/e2e/legacy/servers/express/run.sh b/e2e/legacy/servers/express/run.sh new file mode 100755 index 000000000..aa2c67d61 --- /dev/null +++ b/e2e/legacy/servers/express/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pnpm dev \ No newline at end of file diff --git a/e2e/legacy/servers/express/test.config.json b/e2e/legacy/servers/express/test.config.json new file mode 100644 index 000000000..a794e6fa2 --- /dev/null +++ b/e2e/legacy/servers/express/test.config.json @@ -0,0 +1,46 @@ +{ + "name": "express", + "type": "server", + "language": "typescript", + "x402Version": 1, + "endpoints": [ + { + "path": "/protected", + "method": "GET", + "description": "Protected endpoint requiring payment", + "requiresPayment": true, + "protocolFamily": "evm" + }, + { + "path": "/protected-svm", + "method": "GET", + "description": "Protected endpoint requiring payment on SVM network", + "requiresPayment": true, + "protocolFamily": "svm" + }, + { + "path": "/health", + "method": "GET", + "description": "Health check endpoint", + "health": true + }, + { + "path": "/close", + "method": "POST", + "description": "Graceful shutdown endpoint", + "close": true + } + ], + "environment": { + "required": [ + "PORT", + "EVM_NETWORK", + "SVM_NETWORK", + "EVM_PAYEE_ADDRESS", + "SVM_PAYEE_ADDRESS" + ], + "optional": [ + "FACILITATOR_URL" + ] + } +} \ No newline at end of file diff --git a/examples/typescript/discovery/tsconfig.json b/e2e/legacy/servers/express/tsconfig.json similarity index 100% rename from examples/typescript/discovery/tsconfig.json rename to e2e/legacy/servers/express/tsconfig.json diff --git a/e2e/legacy/servers/fastapi/build.sh b/e2e/legacy/servers/fastapi/build.sh new file mode 100755 index 000000000..f5fbe5e8f --- /dev/null +++ b/e2e/legacy/servers/fastapi/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# Python doesn't require a build step +# This file is intentionally empty +exit 0 + diff --git a/e2e/legacy/servers/fastapi/install.sh b/e2e/legacy/servers/fastapi/install.sh new file mode 100755 index 000000000..90fe119bd --- /dev/null +++ b/e2e/legacy/servers/fastapi/install.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Installing Python dependencies for FastAPI server..." +uv sync +echo "✅ Dependencies installed" + diff --git a/e2e/servers/fastapi/main.py b/e2e/legacy/servers/fastapi/main.py similarity index 83% rename from e2e/servers/fastapi/main.py rename to e2e/legacy/servers/fastapi/main.py index cedbdee40..230ee05b3 100644 --- a/e2e/servers/fastapi/main.py +++ b/e2e/legacy/servers/fastapi/main.py @@ -21,38 +21,27 @@ load_dotenv() # Get configuration from environment -USE_CDP_FACILITATOR = os.getenv("USE_CDP_FACILITATOR", "false").lower() == "true" NETWORK = os.getenv("EVM_NETWORK", "base-sepolia") -ADDRESS = os.getenv("EVM_ADDRESS") +ADDRESS = os.getenv("EVM_PAYEE_ADDRESS") PORT = int(os.getenv("PORT", "4021")) - -# CDP facilitator configuration -CDP_API_KEY_ID = os.getenv("CDP_API_KEY_ID") -CDP_API_KEY_SECRET = os.getenv("CDP_API_KEY_SECRET") +FACILITATOR_URL = os.getenv("FACILITATOR_URL") if not ADDRESS: print("Error: Missing required environment variable ADDRESS") sys.exit(1) -# Validate CDP configuration if using CDP facilitator -if USE_CDP_FACILITATOR and (not CDP_API_KEY_ID or not CDP_API_KEY_SECRET): - print( - "Error: CDP facilitator enabled but missing CDP_API_KEY_ID or CDP_API_KEY_SECRET" - ) - sys.exit(1) - - chain_id = get_chain_id(NETWORK) address = get_default_token_address(chain_id) app = FastAPI() -# Create facilitator config if using CDP +# Create facilitator config if URL is provided facilitator_config = None -if USE_CDP_FACILITATOR: - from cdp.x402 import create_facilitator_config - - facilitator_config = create_facilitator_config(CDP_API_KEY_ID, CDP_API_KEY_SECRET) +if FACILITATOR_URL: + facilitator_config = {"url": FACILITATOR_URL} + print(f"Using remote facilitator at: {FACILITATOR_URL}") +else: + print("Using default facilitator") # Apply payment middleware to protected endpoints app.middleware("http")( @@ -159,7 +148,7 @@ def signal_handler(signum, frame): print(f"Starting FastAPI server on port {PORT}") print(f"Server address: {ADDRESS}") print(f"Network: {NETWORK}") - print(f"Using CDP facilitator: {USE_CDP_FACILITATOR}") + print(f"Using facilitator: {FACILITATOR_URL}") print("Server listening on port", PORT) uvicorn.run(app, host="0.0.0.0", port=PORT, log_level="warning") diff --git a/e2e/servers/fastapi/pyproject.toml b/e2e/legacy/servers/fastapi/pyproject.toml similarity index 88% rename from e2e/servers/fastapi/pyproject.toml rename to e2e/legacy/servers/fastapi/pyproject.toml index 3a1495fb0..b008758ab 100644 --- a/e2e/servers/fastapi/pyproject.toml +++ b/e2e/legacy/servers/fastapi/pyproject.toml @@ -25,4 +25,4 @@ allow-direct-references = true package = false [tool.uv.sources] -x402 = { path = "../../../python/x402", editable = true } \ No newline at end of file +x402 = { path = "../../../../python/x402", editable = true } \ No newline at end of file diff --git a/e2e/servers/fastapi/run.sh b/e2e/legacy/servers/fastapi/run.sh similarity index 100% rename from e2e/servers/fastapi/run.sh rename to e2e/legacy/servers/fastapi/run.sh diff --git a/e2e/servers/fastapi/test.config.json b/e2e/legacy/servers/fastapi/test.config.json similarity index 90% rename from e2e/servers/fastapi/test.config.json rename to e2e/legacy/servers/fastapi/test.config.json index 467c3f037..0c3766291 100644 --- a/e2e/servers/fastapi/test.config.json +++ b/e2e/legacy/servers/fastapi/test.config.json @@ -2,6 +2,7 @@ "name": "fastapi", "type": "server", "language": "python", + "x402Version": 1, "description": "Python FastAPI server with x402 payment middleware", "endpoints": [ { @@ -33,14 +34,12 @@ ], "environment": { "required": [ - "EVM_ADDRESS" + "EVM_PAYEE_ADDRESS" ], "optional": [ "PORT", - "USE_CDP_FACILITATOR", "EVM_NETWORK", - "CDP_API_KEY_ID", - "CDP_API_KEY_SECRET" + "FACILITATOR_URL" ] } } \ No newline at end of file diff --git a/e2e/servers/fastapi/uv.lock b/e2e/legacy/servers/fastapi/uv.lock similarity index 99% rename from e2e/servers/fastapi/uv.lock rename to e2e/legacy/servers/fastapi/uv.lock index 1119ab203..0702c34c7 100644 --- a/e2e/servers/fastapi/uv.lock +++ b/e2e/legacy/servers/fastapi/uv.lock @@ -2119,7 +2119,7 @@ wheels = [ [[package]] name = "x402" version = "0.2.1" -source = { editable = "../../../python/x402" } +source = { editable = "../../../../python/x402" } dependencies = [ { name = "eth-account" }, { name = "eth-typing" }, @@ -2170,7 +2170,7 @@ requires-dist = [ { name = "fastapi", specifier = ">=0.104.0" }, { name = "python-dotenv", specifier = ">=1.0.0" }, { name = "uvicorn", specifier = ">=0.24.0" }, - { name = "x402", editable = "../../../python/x402" }, + { name = "x402", editable = "../../../../python/x402" }, ] [[package]] diff --git a/e2e/legacy/servers/flask/build.sh b/e2e/legacy/servers/flask/build.sh new file mode 100755 index 000000000..f5fbe5e8f --- /dev/null +++ b/e2e/legacy/servers/flask/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# Python doesn't require a build step +# This file is intentionally empty +exit 0 + diff --git a/e2e/legacy/servers/flask/install.sh b/e2e/legacy/servers/flask/install.sh new file mode 100755 index 000000000..ebedd5f75 --- /dev/null +++ b/e2e/legacy/servers/flask/install.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Installing Python dependencies for Flask server..." +uv sync +echo "✅ Dependencies installed" + diff --git a/e2e/servers/flask/main.py b/e2e/legacy/servers/flask/main.py similarity index 78% rename from e2e/servers/flask/main.py rename to e2e/legacy/servers/flask/main.py index 8990c3dbf..f20e5ae79 100644 --- a/e2e/servers/flask/main.py +++ b/e2e/legacy/servers/flask/main.py @@ -14,34 +14,24 @@ load_dotenv() # Get configuration from environment -USE_CDP_FACILITATOR = os.getenv("USE_CDP_FACILITATOR", "false").lower() == "true" NETWORK = os.getenv("EVM_NETWORK", "base-sepolia") -ADDRESS = os.getenv("EVM_ADDRESS") +ADDRESS = os.getenv("EVM_PAYEE_ADDRESS") PORT = int(os.getenv("PORT", "4021")) - -# CDP facilitator configuration -CDP_API_KEY_ID = os.getenv("CDP_API_KEY_ID") -CDP_API_KEY_SECRET = os.getenv("CDP_API_KEY_SECRET") +FACILITATOR_URL = os.getenv("FACILITATOR_URL") if not ADDRESS: print("Error: Missing required environment variable ADDRESS") sys.exit(1) -# Validate CDP configuration if using CDP facilitator -if USE_CDP_FACILITATOR and (not CDP_API_KEY_ID or not CDP_API_KEY_SECRET): - print( - "Error: CDP facilitator enabled but missing CDP_API_KEY_ID or CDP_API_KEY_SECRET" - ) - sys.exit(1) - app = Flask(__name__) -# Create facilitator config if using CDP +# Create facilitator config if URL is provided facilitator_config = None -if USE_CDP_FACILITATOR: - from cdp.x402 import create_facilitator_config - - facilitator_config = create_facilitator_config(CDP_API_KEY_ID, CDP_API_KEY_SECRET) +if FACILITATOR_URL: + facilitator_config = {"url": FACILITATOR_URL} + print(f"Using remote facilitator at: {FACILITATOR_URL}") +else: + print("Using default facilitator") # Initialize payment middleware payment_middleware = PaymentMiddleware(app) @@ -119,7 +109,7 @@ def signal_handler(signum, frame): print(f"Starting Flask server on port {PORT}") print(f"Server address: {ADDRESS}") print(f"Network: {NETWORK}") - print(f"Using CDP facilitator: {USE_CDP_FACILITATOR}") + print(f"Using facilitator: {FACILITATOR_URL}") print("Server listening on port", PORT) app.run( diff --git a/e2e/servers/flask/pyproject.toml b/e2e/legacy/servers/flask/pyproject.toml similarity index 88% rename from e2e/servers/flask/pyproject.toml rename to e2e/legacy/servers/flask/pyproject.toml index 1c67e89f0..f2abc86c0 100644 --- a/e2e/servers/flask/pyproject.toml +++ b/e2e/legacy/servers/flask/pyproject.toml @@ -24,4 +24,4 @@ allow-direct-references = true package = false [tool.uv.sources] -x402 = { path = "../../../python/x402", editable = true } \ No newline at end of file +x402 = { path = "../../../../python/x402", editable = true } \ No newline at end of file diff --git a/e2e/servers/flask/run.sh b/e2e/legacy/servers/flask/run.sh similarity index 100% rename from e2e/servers/flask/run.sh rename to e2e/legacy/servers/flask/run.sh diff --git a/e2e/servers/flask/test.config.json b/e2e/legacy/servers/flask/test.config.json similarity index 87% rename from e2e/servers/flask/test.config.json rename to e2e/legacy/servers/flask/test.config.json index 4a3655561..a6b40e00d 100644 --- a/e2e/servers/flask/test.config.json +++ b/e2e/legacy/servers/flask/test.config.json @@ -2,6 +2,7 @@ "name": "flask", "type": "server", "language": "python", + "x402Version": 1, "description": "Python Flask server with x402 payment middleware", "endpoints": [ { @@ -26,14 +27,12 @@ ], "environment": { "required": [ - "EVM_ADDRESS" + "EVM_PAYEE_ADDRESS" ], "optional": [ "PORT", - "USE_CDP_FACILITATOR", "EVM_NETWORK", - "CDP_API_KEY_ID", - "CDP_API_KEY_SECRET" + "FACILITATOR_URL" ] } } \ No newline at end of file diff --git a/e2e/servers/flask/uv.lock b/e2e/legacy/servers/flask/uv.lock similarity index 99% rename from e2e/servers/flask/uv.lock rename to e2e/legacy/servers/flask/uv.lock index 91000328d..a13cd6857 100644 --- a/e2e/servers/flask/uv.lock +++ b/e2e/legacy/servers/flask/uv.lock @@ -2119,7 +2119,7 @@ wheels = [ [[package]] name = "x402" version = "0.2.1" -source = { editable = "../../../python/x402" } +source = { editable = "../../../../python/x402" } dependencies = [ { name = "eth-account" }, { name = "eth-typing" }, @@ -2168,7 +2168,7 @@ requires-dist = [ { name = "cdp-sdk", specifier = ">=1.15.0" }, { name = "flask", specifier = ">=3.0.0" }, { name = "python-dotenv", specifier = ">=1.0.0" }, - { name = "x402", editable = "../../../python/x402" }, + { name = "x402", editable = "../../../../python/x402" }, ] [[package]] diff --git a/e2e/legacy/servers/gin/build.sh b/e2e/legacy/servers/gin/build.sh new file mode 100755 index 000000000..6d92656a6 --- /dev/null +++ b/e2e/legacy/servers/gin/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Building Gin server (legacy)..." +go build -o gin . +echo "✅ Build completed: gin" + diff --git a/e2e/legacy/servers/gin/gin b/e2e/legacy/servers/gin/gin new file mode 100755 index 000000000..97bddd074 Binary files /dev/null and b/e2e/legacy/servers/gin/gin differ diff --git a/e2e/legacy/servers/gin/go.mod b/e2e/legacy/servers/gin/go.mod new file mode 100644 index 000000000..5c21953de --- /dev/null +++ b/e2e/legacy/servers/gin/go.mod @@ -0,0 +1,42 @@ +module github.com/coinbase/x402/e2e/servers/gin + +go 1.23.3 + +require ( + github.com/coinbase/x402/go v0.0.0-00010101000000-000000000000 + github.com/gin-gonic/gin v1.10.0 + github.com/joho/godotenv v1.5.1 +) + +require ( + github.com/bytedance/sonic v1.13.2 // indirect + github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/cloudwego/base64x v0.1.5 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.0.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.26.0 // indirect + github.com/goccy/go-json v0.10.5 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.15.0 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/net v0.38.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/coinbase/x402/go => ../../../../go/legacy diff --git a/e2e/legacy/servers/gin/go.sum b/e2e/legacy/servers/gin/go.sum new file mode 100644 index 000000000..589bce8e7 --- /dev/null +++ b/e2e/legacy/servers/gin/go.sum @@ -0,0 +1,101 @@ +github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= +github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= +github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= +github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E= +github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= +github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= +golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/e2e/legacy/servers/gin/install.sh b/e2e/legacy/servers/gin/install.sh new file mode 100755 index 000000000..ce5e7630b --- /dev/null +++ b/e2e/legacy/servers/gin/install.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Installing Go dependencies for Gin server (legacy)..." +go mod tidy +echo "✅ Dependencies installed" + diff --git a/e2e/legacy/servers/gin/main.go b/e2e/legacy/servers/gin/main.go new file mode 100644 index 000000000..a3630f022 --- /dev/null +++ b/e2e/legacy/servers/gin/main.go @@ -0,0 +1,142 @@ +package main + +import ( + "fmt" + "math/big" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + x402gin "github.com/coinbase/x402/go/pkg/gin" + "github.com/coinbase/x402/go/pkg/types" + "github.com/gin-gonic/gin" + "github.com/joho/godotenv" +) + +var shutdownRequested bool + +func main() { + // Load .env file if it exists + if err := godotenv.Load(); err != nil { + fmt.Println("Warning: .env file not found. Using environment variables.") + } + + // Get configuration from environment + network := os.Getenv("EVM_NETWORK") + if network == "" { + network = "base-sepolia" + } + address := os.Getenv("EVM_PAYEE_ADDRESS") + port := os.Getenv("PORT") + if port == "" { + port = "4021" + } + facilitatorURL := os.Getenv("FACILITATOR_URL") + + if address == "" { + fmt.Println("Error: Missing required environment variable EVM_PAYEE_ADDRESS") + os.Exit(1) + } + + // Create facilitator config if URL is provided + var facilitatorConfig *types.FacilitatorConfig + if facilitatorURL != "" { + facilitatorConfig = &types.FacilitatorConfig{ + URL: facilitatorURL, + } + fmt.Printf("Using remote facilitator at: %s\n", facilitatorURL) + } else { + fmt.Println("Using default facilitator") + } + + // Set Gin to release mode to reduce logs + gin.SetMode(gin.ReleaseMode) + r := gin.New() + r.Use(gin.Recovery()) + + // Protected endpoint that requires payment + r.GET("/protected", + x402gin.PaymentMiddleware( + big.NewFloat(0.001), // $0.001 USD + address, + x402gin.WithFacilitatorConfig(facilitatorConfig), + x402gin.WithDescription("Protected endpoint requiring payment"), + x402gin.WithResource("http://localhost:"+port+"/protected"), + x402gin.WithTestnet(network == "base-sepolia"), + ), + func(c *gin.Context) { + if shutdownRequested { + c.JSON(http.StatusServiceUnavailable, gin.H{ + "error": "Server shutting down", + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Access granted to protected resource", + "timestamp": "2024-01-01T00:00:00Z", + "data": gin.H{ + "resource": "premium_content", + "access_level": "paid", + }, + }) + }, + ) + + // Health check endpoint + r.GET("/health", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "status": "healthy", + "timestamp": "2024-01-01T00:00:00Z", + "server": "gin", + }) + }) + + // Graceful shutdown endpoint + r.POST("/close", func(c *gin.Context) { + shutdownRequested = true + + c.JSON(http.StatusOK, gin.H{ + "message": "Server shutting down gracefully", + "timestamp": "2024-01-01T00:00:00Z", + }) + + // Schedule server shutdown after response + go func() { + time.Sleep(100 * time.Millisecond) + os.Exit(0) + }() + }) + + // Set up graceful shutdown + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) + + go func() { + <-quit + fmt.Println("Received shutdown signal, exiting...") + os.Exit(0) + }() + + fmt.Printf("Starting Gin server on port %s\n", port) + fmt.Printf("Server address: %s\n", address) + fmt.Printf("Network: %s\n", network) + if facilitatorURL != "" { + fmt.Printf("Using facilitator: %s\n", facilitatorURL) + } else { + fmt.Printf("Using default facilitator\n") + } + fmt.Printf("Server listening on port %s\n", port) + + server := &http.Server{ + Addr: ":" + port, + Handler: r, + } + + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + fmt.Printf("Error starting server: %v\n", err) + os.Exit(1) + } +} diff --git a/e2e/legacy/servers/gin/run.sh b/e2e/legacy/servers/gin/run.sh new file mode 100644 index 000000000..00637611b --- /dev/null +++ b/e2e/legacy/servers/gin/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +go run main.go \ No newline at end of file diff --git a/e2e/legacy/servers/gin/test.config.json b/e2e/legacy/servers/gin/test.config.json new file mode 100644 index 000000000..c67cfb847 --- /dev/null +++ b/e2e/legacy/servers/gin/test.config.json @@ -0,0 +1,38 @@ +{ + "name": "gin", + "type": "server", + "language": "go", + "x402Version": 1, + "description": "Go Gin server with x402 payment middleware", + "endpoints": [ + { + "path": "/protected", + "method": "GET", + "description": "Protected endpoint requiring payment", + "requiresPayment": true, + "protocolFamily": "evm" + }, + { + "path": "/health", + "method": "GET", + "description": "Health check endpoint", + "health": true + }, + { + "path": "/close", + "method": "POST", + "description": "Graceful shutdown endpoint", + "close": true + } + ], + "environment": { + "required": [ + "EVM_PAYEE_ADDRESS" + ], + "optional": [ + "PORT", + "EVM_NETWORK", + "FACILITATOR_URL" + ] + } +} \ No newline at end of file diff --git a/e2e/legacy/servers/hono/.env-local b/e2e/legacy/servers/hono/.env-local new file mode 100644 index 000000000..9e299111b --- /dev/null +++ b/e2e/legacy/servers/hono/.env-local @@ -0,0 +1,7 @@ +FACILITATOR_URL=https://x402.org/facilitator +NETWORK=base-sepolia +ADDRESS= + +# required if using the Base mainnet facilitator +CDP_API_KEY_ID="Coinbase Developer Platform Key" +CDP_API_KEY_SECRET="Coinbase Developer Platform Key Secret" \ No newline at end of file diff --git a/examples/typescript/discovery/.prettierignore b/e2e/legacy/servers/hono/.prettierignore similarity index 100% rename from examples/typescript/discovery/.prettierignore rename to e2e/legacy/servers/hono/.prettierignore diff --git a/examples/typescript/discovery/.prettierrc b/e2e/legacy/servers/hono/.prettierrc similarity index 100% rename from examples/typescript/discovery/.prettierrc rename to e2e/legacy/servers/hono/.prettierrc diff --git a/e2e/legacy/servers/hono/README.md b/e2e/legacy/servers/hono/README.md new file mode 100644 index 000000000..34cfba848 --- /dev/null +++ b/e2e/legacy/servers/hono/README.md @@ -0,0 +1,150 @@ +# x402-hono Example Server + +This is an example Hono server that demonstrates how to use the `x402-hono` middleware to implement paywall functionality in your API endpoints. + +## Prerequisites + +- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) +- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) +- A valid Ethereum address for receiving payments +- Coinbase Developer Platform API Key & Secret (if accepting payments on Base mainnet) +-- get them here [https://portal.cdp.coinbase.com/projects](https://portal.cdp.coinbase.com/projects) + +## Setup + +1. Copy `.env-local` to `.env` and add your Ethereum address to receive payments: + +```bash +cp .env-local .env +``` + +2. Install and build all packages from the typescript examples root: + +```bash +cd ../../ +pnpm install +pnpm build +cd servers/hono +``` + +3. Run the server + +```bash +pnpm install +pnpm dev +``` + +## Testing the Server + +You can test the server using one of the example clients: + +### Using the Fetch Client + +```bash +cd ../clients/fetch +# Ensure .env is setup +pnpm install +pnpm dev +``` + +### Using the Axios Client + +```bash +cd ../clients/axios +# Ensure .env is setup +pnpm install +pnpm dev +``` + +These clients will demonstrate how to: + +1. Make an initial request to get payment requirements +2. Process the payment requirements +3. Make a second request with the payment token + +## Example Endpoint + +The server includes a single example endpoint at `/weather` that requires a payment of $0.001 to access. The endpoint returns a simple weather report. + +## Response Format + +### Payment Required (402) + +```json +{ + "error": "X-PAYMENT header is required", + "paymentRequirements": { + "scheme": "exact", + "network": "base", + "maxAmountRequired": "1000", + "resource": "http://localhost:4021/weather", + "description": "", + "mimeType": "", + "payTo": "0xYourAddress", + "maxTimeoutSeconds": 60, + "asset": "0x...", + "outputSchema": null, + "extra": null + } +} +``` + +### Successful Response + +```ts +// Body +{ + "report": { + "weather": "sunny", + "temperature": 70 + } +} +// Headers +{ + "X-PAYMENT-RESPONSE": "..." // Encoded response object +} +``` + +## Extending the Example + +To add more paid endpoints, follow this pattern: + +```typescript +// First, configure the payment middleware with your routes +app.use( + paymentMiddleware(payTo, { + // Define your routes and their payment requirements + "/your-endpoint": { + price: "$0.10", + network, + }, + "/premium/*": { + price: { + amount: "100000", + asset: { + address: "0xabc", + decimals: 18, + eip712: { + name: "WETH", + version: "1", + }, + }, + }, + network, + }, + }), +); + +// Then define your routes as normal +app.get("/your-endpoint", c => { + return c.json({ + // Your response data + }); +}); + +app.get("/premium/content", c => { + return c.json({ + content: "This is premium content", + }); +}); +``` diff --git a/e2e/legacy/servers/hono/build.sh b/e2e/legacy/servers/hono/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/legacy/servers/hono/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/legacy/servers/hono/eslint.config.js b/e2e/legacy/servers/hono/eslint.config.js new file mode 100644 index 000000000..e2fde7b3b --- /dev/null +++ b/e2e/legacy/servers/hono/eslint.config.js @@ -0,0 +1,73 @@ +import js from "@eslint/js"; +import ts from "@typescript-eslint/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; +import prettier from "eslint-plugin-prettier"; +import jsdoc from "eslint-plugin-jsdoc"; +import importPlugin from "eslint-plugin-import"; + +export default [ + { + ignores: ["dist/**", "node_modules/**"], + }, + { + files: ["**/*.ts"], + languageOptions: { + parser: tsParser, + sourceType: "module", + ecmaVersion: 2020, + globals: { + process: "readonly", + __dirname: "readonly", + module: "readonly", + require: "readonly", + Buffer: "readonly", + console: "readonly", + exports: "readonly", + setTimeout: "readonly", + clearTimeout: "readonly", + setInterval: "readonly", + clearInterval: "readonly", + }, + }, + plugins: { + "@typescript-eslint": ts, + prettier: prettier, + jsdoc: jsdoc, + import: importPlugin, + }, + rules: { + ...ts.configs.recommended.rules, + "import/first": "error", + "prettier/prettier": "error", + "@typescript-eslint/member-ordering": "error", + "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_$" }], + "jsdoc/tag-lines": ["error", "any", { startLines: 1 }], + "jsdoc/check-alignment": "error", + "jsdoc/no-undefined-types": "off", + "jsdoc/check-param-names": "error", + "jsdoc/check-tag-names": "error", + "jsdoc/check-types": "error", + "jsdoc/implements-on-classes": "error", + "jsdoc/require-description": "error", + "jsdoc/require-jsdoc": [ + "error", + { + require: { + FunctionDeclaration: true, + MethodDefinition: true, + ClassDeclaration: true, + ArrowFunctionExpression: false, + FunctionExpression: false, + }, + }, + ], + "jsdoc/require-param": "error", + "jsdoc/require-param-description": "error", + "jsdoc/require-param-type": "off", + "jsdoc/require-returns": "error", + "jsdoc/require-returns-description": "error", + "jsdoc/require-returns-type": "off", + "jsdoc/require-hyphen-before-param-description": ["error", "always"], + }, + }, +]; diff --git a/e2e/legacy/servers/hono/index.ts b/e2e/legacy/servers/hono/index.ts new file mode 100644 index 000000000..4580e4eb3 --- /dev/null +++ b/e2e/legacy/servers/hono/index.ts @@ -0,0 +1,77 @@ +import { config } from "dotenv"; +import { Hono } from "hono"; +import { serve } from "@hono/node-server"; +import { paymentMiddleware, Network, Resource, FacilitatorConfig } from "x402-hono"; + +config(); + +const payTo = process.env.EVM_PAYEE_ADDRESS as `0x${string}`; +const network = process.env.EVM_NETWORK as Network; +const port = parseInt(process.env.PORT || '4021'); +const facilitatorUrl = process.env.FACILITATOR_URL; + +if (!payTo || !network) { + console.error("Missing required environment variables"); + process.exit(1); +} + +// Create facilitator config if URL is provided +const facilitatorConfig: FacilitatorConfig | undefined = facilitatorUrl + ? { url: facilitatorUrl as Resource } + : undefined; + +if (facilitatorUrl) { + console.log(`Using remote facilitator at: ${facilitatorUrl}`); +} else { + console.log(`Using default facilitator`); +} + +const app = new Hono(); + +// Apply payment middleware to protected endpoint +app.use( + paymentMiddleware( + payTo, + { + "/protected": { + price: "$0.001", + network, + }, + }, + facilitatorConfig, + ), +); + +// Protected endpoint requiring payment +app.get("/protected", c => { + return c.json({ + message: "Protected endpoint accessed successfully", + timestamp: new Date().toISOString() + }); +}); + +// Health check endpoint +app.get("/health", c => { + return c.json({ + status: "healthy" + }); +}); + +// Graceful shutdown endpoint +app.post("/close", c => { + console.log("Received shutdown request"); + setTimeout(() => { + process.exit(0); + }, 1000); + + return c.json({ + message: "Shutting down gracefully" + }); +}); + +serve({ + fetch: app.fetch, + port, +}); + +console.log("Server listening on port", port); diff --git a/e2e/legacy/servers/hono/install.sh b/e2e/legacy/servers/hono/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/legacy/servers/hono/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/legacy/servers/hono/package.json b/e2e/legacy/servers/hono/package.json new file mode 100644 index 000000000..4f0cefc63 --- /dev/null +++ b/e2e/legacy/servers/hono/package.json @@ -0,0 +1,31 @@ +{ + "name": "hono-server-example", + "private": true, + "type": "module", + "scripts": { + "dev": "tsx index.ts", + "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", + "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", + "lint": "eslint . --ext .ts --fix", + "lint:check": "eslint . --ext .ts" + }, + "dependencies": { + "@hono/node-server": "^1.13.8", + "dotenv": "^16.4.7", + "hono": "^4.7.1", + "x402-hono": "workspace:*" + }, + "devDependencies": { + "tsup": "^7.2.0", + "tsx": "^4.7.0", + "typescript": "^5.3.0", + "@eslint/js": "^9.24.0", + "eslint": "^9.24.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "eslint-plugin-import": "^2.31.0", + "prettier": "3.5.2" + } +} diff --git a/e2e/legacy/servers/hono/run.sh b/e2e/legacy/servers/hono/run.sh new file mode 100755 index 000000000..aa2c67d61 --- /dev/null +++ b/e2e/legacy/servers/hono/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pnpm dev \ No newline at end of file diff --git a/e2e/legacy/servers/hono/test.config.json b/e2e/legacy/servers/hono/test.config.json new file mode 100644 index 000000000..b0935c390 --- /dev/null +++ b/e2e/legacy/servers/hono/test.config.json @@ -0,0 +1,37 @@ +{ + "name": "hono", + "type": "server", + "language": "typescript", + "x402Version": 1, + "endpoints": [ + { + "path": "/protected", + "method": "GET", + "description": "Protected endpoint requiring payment", + "requiresPayment": true, + "protocolFamily": "evm" + }, + { + "path": "/health", + "method": "GET", + "description": "Health check endpoint", + "health": true + }, + { + "path": "/close", + "method": "POST", + "description": "Graceful shutdown endpoint", + "close": true + } + ], + "environment": { + "required": [ + "PORT", + "EVM_NETWORK", + "EVM_PAYEE_ADDRESS" + ], + "optional": [ + "FACILITATOR_URL" + ] + } +} \ No newline at end of file diff --git a/examples/typescript/servers/mainnet/tsconfig.json b/e2e/legacy/servers/hono/tsconfig.json similarity index 100% rename from examples/typescript/servers/mainnet/tsconfig.json rename to e2e/legacy/servers/hono/tsconfig.json diff --git a/e2e/legacy/servers/next/.env-local b/e2e/legacy/servers/next/.env-local new file mode 100644 index 000000000..922c51636 --- /dev/null +++ b/e2e/legacy/servers/next/.env-local @@ -0,0 +1,3 @@ +NEXT_PUBLIC_FACILITATOR_URL=https://x402.org/facilitator +NETWORK=base-sepolia +RESOURCE_WALLET_ADDRESS= diff --git a/examples/typescript/fullstack/mainnet/.gitignore b/e2e/legacy/servers/next/.gitignore similarity index 100% rename from examples/typescript/fullstack/mainnet/.gitignore rename to e2e/legacy/servers/next/.gitignore diff --git a/examples/typescript/facilitator/.prettierignore b/e2e/legacy/servers/next/.prettierignore similarity index 100% rename from examples/typescript/facilitator/.prettierignore rename to e2e/legacy/servers/next/.prettierignore diff --git a/examples/typescript/facilitator/.prettierrc b/e2e/legacy/servers/next/.prettierrc similarity index 100% rename from examples/typescript/facilitator/.prettierrc rename to e2e/legacy/servers/next/.prettierrc diff --git a/examples/typescript/fullstack/mainnet/README.md b/e2e/legacy/servers/next/README.md similarity index 80% rename from examples/typescript/fullstack/mainnet/README.md rename to e2e/legacy/servers/next/README.md index 623b583f2..87fb5e128 100644 --- a/examples/typescript/fullstack/mainnet/README.md +++ b/e2e/legacy/servers/next/README.md @@ -4,7 +4,7 @@ This is a Next.js application that demonstrates how to use the `x402-next` middl ## Prerequisites -- Node.js v22+ (install via [nvm](https://github.com/nvm-sh/nvm)) +- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) - pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) - A valid Ethereum address for receiving payments @@ -21,7 +21,7 @@ cp .env.local .env cd ../../ pnpm install pnpm build -cd fullstack/mainnet +cd fullstack/next ``` 2. Install and start the Next.js example: @@ -34,33 +34,35 @@ pnpm dev The app includes protected routes that require payment to access: ### Protected Page Route -The `/protected` route requires a payment of $0.001 to access. The route is protected using the x402-next middleware: +The `/protected` route requires a payment of $0.01 to access. The route is protected using the x402-next middleware: ```typescript // middleware.ts import { paymentMiddleware, Network, Resource } from "x402-next"; -import { facilitator } from "@coinbase/x402"; +const facilitatorUrl = process.env.NEXT_PUBLIC_FACILITATOR_URL as Resource; const payTo = process.env.RESOURCE_WALLET_ADDRESS as Address; +const network = process.env.NETWORK as Network; export const middleware = paymentMiddleware( payTo, { "/protected": { - price: "$0.001", - network: "base", + price: "$0.01", + network, config: { description: "Access to protected content", }, }, }, - facilitator + { + url: facilitatorUrl, + }, ); // Configure which paths the middleware should run on export const config = { matcher: ["/protected/:path*"], - runtime: "nodejs", }; ``` @@ -103,15 +105,15 @@ export const middleware = paymentMiddleware( payTo, { "/protected": { - price: "$0.001", - network: "base", + price: "$0.01", + network, config: { description: "Access to protected content", }, }, "/api/premium": { - price: "$0.01", - network: "base", + price: "$0.10", + network, config: { description: "Premium API access", }, @@ -121,10 +123,5 @@ export const middleware = paymentMiddleware( export const config = { matcher: ["/protected/:path*", "/api/premium/:path*"], - runtime: "nodejs", }; ``` - -## Accessing Mainnet - -To access the mainnet facilitator in Next.js, simply install and use the `@coinbase/x402` package. \ No newline at end of file diff --git a/e2e/legacy/servers/next/app/api/close/route.ts b/e2e/legacy/servers/next/app/api/close/route.ts new file mode 100644 index 000000000..d2132c17c --- /dev/null +++ b/e2e/legacy/servers/next/app/api/close/route.ts @@ -0,0 +1,23 @@ +import { NextResponse } from "next/server"; + +/** + * Graceful shutdown endpoint + */ +export const runtime = "nodejs"; + +/** + * Graceful shutdown endpoint + */ +export async function POST() { + console.log("Received shutdown request"); + + // Simple approach: exit after a short delay to allow response to be sent + setTimeout(() => { + console.log("Shutting down Next.js server"); + process.exit(0); + }, 1000); + + return NextResponse.json({ + message: "Shutting down gracefully", + }); +} \ No newline at end of file diff --git a/e2e/legacy/servers/next/app/api/health/route.ts b/e2e/legacy/servers/next/app/api/health/route.ts new file mode 100644 index 000000000..8a57257b3 --- /dev/null +++ b/e2e/legacy/servers/next/app/api/health/route.ts @@ -0,0 +1,15 @@ +import { NextResponse } from "next/server"; + +/** + * Health check endpoint + */ +export const runtime = "nodejs"; + +/** + * Health check endpoint + */ +export async function GET() { + return NextResponse.json({ + status: "healthy", + }); +} \ No newline at end of file diff --git a/e2e/servers/next/app/api/protected/route.ts b/e2e/legacy/servers/next/app/api/protected/route.ts similarity index 100% rename from e2e/servers/next/app/api/protected/route.ts rename to e2e/legacy/servers/next/app/api/protected/route.ts diff --git a/examples/typescript/fullstack/mainnet/app/assets/x402_wordmark_dark.png b/e2e/legacy/servers/next/app/assets/x402_wordmark_dark.png similarity index 100% rename from examples/typescript/fullstack/mainnet/app/assets/x402_wordmark_dark.png rename to e2e/legacy/servers/next/app/assets/x402_wordmark_dark.png diff --git a/examples/typescript/fullstack/mainnet/app/assets/x402_wordmark_dark.svg b/e2e/legacy/servers/next/app/assets/x402_wordmark_dark.svg similarity index 100% rename from examples/typescript/fullstack/mainnet/app/assets/x402_wordmark_dark.svg rename to e2e/legacy/servers/next/app/assets/x402_wordmark_dark.svg diff --git a/examples/typescript/fullstack/mainnet/app/assets/x402_wordmark_light.svg b/e2e/legacy/servers/next/app/assets/x402_wordmark_light.svg similarity index 100% rename from examples/typescript/fullstack/mainnet/app/assets/x402_wordmark_light.svg rename to e2e/legacy/servers/next/app/assets/x402_wordmark_light.svg diff --git a/examples/typescript/fullstack/mainnet/app/favicon.ico b/e2e/legacy/servers/next/app/favicon.ico similarity index 100% rename from examples/typescript/fullstack/mainnet/app/favicon.ico rename to e2e/legacy/servers/next/app/favicon.ico diff --git a/examples/typescript/fullstack/mainnet/app/globals.css b/e2e/legacy/servers/next/app/globals.css similarity index 100% rename from examples/typescript/fullstack/mainnet/app/globals.css rename to e2e/legacy/servers/next/app/globals.css diff --git a/examples/typescript/fullstack/mainnet/app/layout.tsx b/e2e/legacy/servers/next/app/layout.tsx similarity index 100% rename from examples/typescript/fullstack/mainnet/app/layout.tsx rename to e2e/legacy/servers/next/app/layout.tsx diff --git a/examples/typescript/fullstack/mainnet/app/page.tsx b/e2e/legacy/servers/next/app/page.tsx similarity index 100% rename from examples/typescript/fullstack/mainnet/app/page.tsx rename to e2e/legacy/servers/next/app/page.tsx diff --git a/examples/typescript/fullstack/mainnet/app/protected/page.tsx b/e2e/legacy/servers/next/app/protected/page.tsx similarity index 100% rename from examples/typescript/fullstack/mainnet/app/protected/page.tsx rename to e2e/legacy/servers/next/app/protected/page.tsx diff --git a/e2e/legacy/servers/next/build.sh b/e2e/legacy/servers/next/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/legacy/servers/next/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/legacy/servers/next/eslint.config.js b/e2e/legacy/servers/next/eslint.config.js new file mode 100644 index 000000000..adbf24d2f --- /dev/null +++ b/e2e/legacy/servers/next/eslint.config.js @@ -0,0 +1,73 @@ +import js from "@eslint/js"; +import ts from "@typescript-eslint/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; +import prettier from "eslint-plugin-prettier"; +import jsdoc from "eslint-plugin-jsdoc"; +import importPlugin from "eslint-plugin-import"; + +export default [ + { + ignores: ["dist/**", "node_modules/**", ".next/**"], + }, + { + files: ["**/*.ts"], + languageOptions: { + parser: tsParser, + sourceType: "module", + ecmaVersion: 2020, + globals: { + process: "readonly", + __dirname: "readonly", + module: "readonly", + require: "readonly", + Buffer: "readonly", + console: "readonly", + exports: "readonly", + setTimeout: "readonly", + clearTimeout: "readonly", + setInterval: "readonly", + clearInterval: "readonly", + }, + }, + plugins: { + "@typescript-eslint": ts, + prettier: prettier, + jsdoc: jsdoc, + import: importPlugin, + }, + rules: { + ...ts.configs.recommended.rules, + "import/first": "error", + "prettier/prettier": "error", + "@typescript-eslint/member-ordering": "error", + "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_$" }], + "jsdoc/tag-lines": ["error", "any", { startLines: 1 }], + "jsdoc/check-alignment": "error", + "jsdoc/no-undefined-types": "off", + "jsdoc/check-param-names": "error", + "jsdoc/check-tag-names": "error", + "jsdoc/check-types": "error", + "jsdoc/implements-on-classes": "error", + "jsdoc/require-description": "error", + "jsdoc/require-jsdoc": [ + "error", + { + require: { + FunctionDeclaration: true, + MethodDefinition: true, + ClassDeclaration: true, + ArrowFunctionExpression: false, + FunctionExpression: false, + }, + }, + ], + "jsdoc/require-param": "error", + "jsdoc/require-param-description": "error", + "jsdoc/require-param-type": "off", + "jsdoc/require-returns": "error", + "jsdoc/require-returns-description": "error", + "jsdoc/require-returns-type": "off", + "jsdoc/require-hyphen-before-param-description": ["error", "always"], + }, + }, +]; diff --git a/e2e/legacy/servers/next/install.sh b/e2e/legacy/servers/next/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/legacy/servers/next/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/servers/next/middleware.ts b/e2e/legacy/servers/next/middleware.ts similarity index 55% rename from e2e/servers/next/middleware.ts rename to e2e/legacy/servers/next/middleware.ts index b019da584..70bc8b80d 100644 --- a/e2e/servers/next/middleware.ts +++ b/e2e/legacy/servers/next/middleware.ts @@ -1,16 +1,21 @@ import { Address } from "viem"; -import { paymentMiddleware, Network, Resource } from "x402-next"; -import { facilitator } from "@coinbase/x402"; +import { paymentMiddleware, Network, Resource, FacilitatorConfig } from "x402-next"; -const useCdpFacilitator = process.env.USE_CDP_FACILITATOR === 'true'; -const payTo = process.env.EVM_ADDRESS as Address; +const payTo = process.env.EVM_PAYEE_ADDRESS as Address; const network = process.env.EVM_NETWORK as Network; +const facilitatorUrl = process.env.FACILITATOR_URL; -// Configure facilitator -const facilitatorConfig = useCdpFacilitator - ? facilitator +// Create facilitator config if URL is provided +const facilitatorConfig: FacilitatorConfig | undefined = facilitatorUrl + ? { url: facilitatorUrl as Resource } : undefined; +if (facilitatorUrl) { + console.log(`Using remote facilitator at: ${facilitatorUrl}`); +} else { + console.log(`Using default facilitator`); +} + export const middleware = paymentMiddleware( payTo, { diff --git a/e2e/legacy/servers/next/next.config.ts b/e2e/legacy/servers/next/next.config.ts new file mode 100644 index 000000000..11b061907 --- /dev/null +++ b/e2e/legacy/servers/next/next.config.ts @@ -0,0 +1,31 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + experimental: { + nodeMiddleware: true, // TEMPORARY: Only needed until Edge runtime support is added + }, + env: { + EVM_PAYEE_ADDRESS: process.env.EVM_PAYEE_ADDRESS, + EVM_NETWORK: process.env.EVM_NETWORK, + FACILITATOR_URL: process.env.FACILITATOR_URL, + PORT: process.env.PORT, + }, + webpack(config) { + config.module.rules.push({ + test: /\.svg$/, + use: ["@svgr/webpack"], + }); + + // Handle Node.js modules that might not be compatible with Edge Runtime + config.resolve.fallback = { + ...config.resolve.fallback, + crypto: require.resolve("crypto-browserify"), + stream: require.resolve("stream-browserify"), + buffer: require.resolve("buffer"), + }; + + return config; + }, +}; + +export default nextConfig; diff --git a/e2e/servers/next/package-lock.json b/e2e/legacy/servers/next/package-lock.json similarity index 100% rename from e2e/servers/next/package-lock.json rename to e2e/legacy/servers/next/package-lock.json diff --git a/e2e/legacy/servers/next/package.json b/e2e/legacy/servers/next/package.json new file mode 100644 index 000000000..ce1d59440 --- /dev/null +++ b/e2e/legacy/servers/next/package.json @@ -0,0 +1,44 @@ +{ + "name": "next-example", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "NODE_NO_WARNINGS=1 next dev -p ${PORT:-4021}", + "build": "next build", + "start": "next start", + "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", + "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", + "lint": "eslint . --ext .ts --fix", + "lint:check": "eslint . --ext .ts" + }, + "dependencies": { + "@heroicons/react": "^2.2.0", + "next": "^15.5.7", + "react": "19.2.1", + "react-dom": "19.2.1", + "viem": "^2.21.26", + "x402-next": "workspace:*" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@svgr/webpack": "^8.1.0", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "buffer": "^6.0.3", + "crypto-browserify": "^3.12.1", + "eslint": "^9.24.0", + "eslint-config-next": "15.1.9", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", + "postcss": "^8", + "prettier": "3.5.2", + "stream-browserify": "^3.0.0", + "tailwindcss": "^3.4.1", + "typescript": "^5" + } +} \ No newline at end of file diff --git a/examples/typescript/fullstack/farcaster-miniapp/postcss.config.mjs b/e2e/legacy/servers/next/postcss.config.mjs similarity index 100% rename from examples/typescript/fullstack/farcaster-miniapp/postcss.config.mjs rename to e2e/legacy/servers/next/postcss.config.mjs diff --git a/examples/typescript/fullstack/mainnet/public/apple-touch-icon.png b/e2e/legacy/servers/next/public/apple-touch-icon.png similarity index 100% rename from examples/typescript/fullstack/mainnet/public/apple-touch-icon.png rename to e2e/legacy/servers/next/public/apple-touch-icon.png diff --git a/examples/typescript/fullstack/mainnet/public/favicon-96x96.png b/e2e/legacy/servers/next/public/favicon-96x96.png similarity index 100% rename from examples/typescript/fullstack/mainnet/public/favicon-96x96.png rename to e2e/legacy/servers/next/public/favicon-96x96.png diff --git a/examples/typescript/fullstack/mainnet/public/favicon.svg b/e2e/legacy/servers/next/public/favicon.svg similarity index 100% rename from examples/typescript/fullstack/mainnet/public/favicon.svg rename to e2e/legacy/servers/next/public/favicon.svg diff --git a/examples/typescript/fullstack/mainnet/public/site.webmanifest b/e2e/legacy/servers/next/public/site.webmanifest similarity index 100% rename from examples/typescript/fullstack/mainnet/public/site.webmanifest rename to e2e/legacy/servers/next/public/site.webmanifest diff --git a/examples/typescript/fullstack/mainnet/public/web-app-manifest-192x192.png b/e2e/legacy/servers/next/public/web-app-manifest-192x192.png similarity index 100% rename from examples/typescript/fullstack/mainnet/public/web-app-manifest-192x192.png rename to e2e/legacy/servers/next/public/web-app-manifest-192x192.png diff --git a/examples/typescript/fullstack/mainnet/public/web-app-manifest-512x512.png b/e2e/legacy/servers/next/public/web-app-manifest-512x512.png similarity index 100% rename from examples/typescript/fullstack/mainnet/public/web-app-manifest-512x512.png rename to e2e/legacy/servers/next/public/web-app-manifest-512x512.png diff --git a/examples/typescript/fullstack/mainnet/public/x402-icon-blue.png b/e2e/legacy/servers/next/public/x402-icon-blue.png similarity index 100% rename from examples/typescript/fullstack/mainnet/public/x402-icon-blue.png rename to e2e/legacy/servers/next/public/x402-icon-blue.png diff --git a/e2e/legacy/servers/next/run.sh b/e2e/legacy/servers/next/run.sh new file mode 100755 index 000000000..aa2c67d61 --- /dev/null +++ b/e2e/legacy/servers/next/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pnpm dev \ No newline at end of file diff --git a/examples/typescript/fullstack/mainnet/tailwind.config.ts b/e2e/legacy/servers/next/tailwind.config.ts similarity index 100% rename from examples/typescript/fullstack/mainnet/tailwind.config.ts rename to e2e/legacy/servers/next/tailwind.config.ts diff --git a/e2e/legacy/servers/next/test.config.json b/e2e/legacy/servers/next/test.config.json new file mode 100644 index 000000000..1a07d3c41 --- /dev/null +++ b/e2e/legacy/servers/next/test.config.json @@ -0,0 +1,37 @@ +{ + "name": "next", + "type": "server", + "language": "typescript", + "x402Version": 1, + "endpoints": [ + { + "path": "/api/protected", + "method": "GET", + "description": "Protected API endpoint requiring payment", + "requiresPayment": true, + "protocolFamily": "evm" + }, + { + "path": "/api/health", + "method": "GET", + "description": "Health check endpoint", + "health": true + }, + { + "path": "/api/close", + "method": "POST", + "description": "Graceful shutdown endpoint", + "close": true + } + ], + "environment": { + "required": [ + "PORT", + "EVM_NETWORK", + "EVM_PAYEE_ADDRESS" + ], + "optional": [ + "FACILITATOR_URL" + ] + } +} \ No newline at end of file diff --git a/e2e/legacy/servers/next/tsconfig.json b/e2e/legacy/servers/next/tsconfig.json new file mode 100644 index 000000000..7060fc92a --- /dev/null +++ b/e2e/legacy/servers/next/tsconfig.json @@ -0,0 +1,42 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./*" + ] + } + }, + "include": [ + "types/video.d.ts", + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/examples/typescript/fullstack/mainnet/types/svg.d.ts b/e2e/legacy/servers/next/types/svg.d.ts similarity index 100% rename from examples/typescript/fullstack/mainnet/types/svg.d.ts rename to e2e/legacy/servers/next/types/svg.d.ts diff --git a/e2e/package.json b/e2e/package.json index fbdf38b92..dc41cf2e3 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -4,25 +4,27 @@ "description": "End-to-end tests for X402 protocol", "main": "dist/test.js", "scripts": { - "build": "tsc", "test": "tsx test.ts", "test:watch": "tsc --watch", - "clean": "rm -rf dist" + "setup": "./setup.sh", + "setup:legacy": "./setup.sh --legacy", + "install:all": "pnpm install && ./setup.sh", + "install:all:legacy": "pnpm install && ./setup.sh --legacy", + "clean": "rm -rf dist", + "clean:ports": "lsof -ti:4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033 | xargs kill -9 2>/dev/null || echo 'Ports cleared'" }, "dependencies": { - "@coinbase/x402": "workspace:*", "axios": "^1.6.0", "dotenv": "^17.0.1", "express": "^4.18.0", + "prompts": "^2.4.2", "tsx": "^4.20.3", - "viem": "^2.0.0", - "x402": "workspace:*", - "x402-axios": "workspace:*", - "x402-express": "workspace:*" + "viem": "^2.0.0" }, "devDependencies": { "@types/express": "^4.17.0", "@types/node": "^20.0.0", + "@types/prompts": "^2.4.9", "typescript": "^5.0.0" }, "engines": { diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index 3f602602a..de1e8f6c7 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -8,9 +8,6 @@ importers: .: dependencies: - '@coinbase/x402': - specifier: workspace:* - version: link:../typescript/packages/coinbase-x402 axios: specifier: ^1.6.0 version: 1.10.0 @@ -20,21 +17,15 @@ importers: express: specifier: ^4.18.0 version: 4.21.2 + prompts: + specifier: ^2.4.2 + version: 2.4.2 tsx: specifier: ^4.20.3 version: 4.20.3 viem: specifier: ^2.0.0 version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402: - specifier: workspace:* - version: link:../typescript/packages/x402 - x402-axios: - specifier: workspace:* - version: link:../typescript/packages/x402-axios - x402-express: - specifier: workspace:* - version: link:../typescript/packages/x402-express devDependencies: '@types/express': specifier: ^4.17.0 @@ -42,55 +33,49 @@ importers: '@types/node': specifier: ^20.0.0 version: 20.19.4 + '@types/prompts': + specifier: ^2.4.9 + version: 2.4.9 typescript: specifier: ^5.0.0 version: 5.8.3 - ../typescript/packages/coinbase-x402: + ../typescript/packages/core: dependencies: - '@coinbase/cdp-sdk': - specifier: ^1.29.0 - version: 1.38.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - viem: - specifier: ^2.21.26 - version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402: - specifier: workspace:^ - version: link:../x402 zod: specifier: ^3.24.2 version: 3.25.71 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 '@types/node': specifier: ^22.13.4 version: 22.16.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -99,116 +84,56 @@ importers: version: 5.8.3 vite: specifier: ^6.2.6 - version: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - ../typescript/packages/x402: + ../typescript/packages/extensions: dependencies: - '@scure/base': - specifier: ^1.2.6 - version: 1.2.6 - '@solana-program/compute-budget': - specifier: ^0.11.0 - version: 0.11.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/token': - specifier: ^0.9.0 - version: 0.9.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/token-2022': - specifier: ^0.6.1 - version: 0.6.1(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) - '@solana/kit': - specifier: ^5.0.0 - version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/transaction-confirmation': - specifier: ^5.0.0 - version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/wallet-standard-features': - specifier: ^1.3.0 - version: 1.3.0 - '@wallet-standard/app': - specifier: ^1.1.0 - version: 1.1.0 - '@wallet-standard/base': - specifier: ^1.1.0 - version: 1.1.0 - '@wallet-standard/features': - specifier: ^1.1.0 - version: 1.1.0 - viem: - specifier: ^2.21.26 - version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - wagmi: - specifier: ^2.15.6 - version: 2.15.6(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.2.1))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) + '@x402/core': + specifier: workspace:* + version: link:../core + ajv: + specifier: ^8.17.1 + version: 8.17.1 zod: specifier: ^3.24.2 version: 3.25.71 devDependencies: - '@coinbase/onchainkit': - specifier: ^0.38.14 - version: 0.38.15(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(bufferutil@4.0.9)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) - '@craftamap/esbuild-plugin-html': - specifier: ^0.9.0 - version: 0.9.0(bufferutil@4.0.9)(esbuild@0.25.5)(utf-8-validate@5.0.10) '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 '@types/node': specifier: ^22.13.4 version: 22.16.0 - '@types/react': - specifier: ^19 - version: 19.1.8 - '@types/react-dom': - specifier: ^19 - version: 19.1.6(@types/react@19.1.8) '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - '@wagmi/connectors': - specifier: ^5.8.1 - version: 5.8.5(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) - '@wagmi/core': - specifier: ^2.17.1 - version: 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) - buffer: - specifier: ^6.0.3 - version: 6.0.3 - esbuild: - specifier: ^0.25.4 - version: 0.25.5 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 - react: - specifier: 19.2.1 - version: 19.2.1 - react-dom: - specifier: 19.2.1 - version: 19.2.1(react@19.2.1) tsup: specifier: ^8.4.0 - version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -217,59 +142,56 @@ importers: version: 5.8.3 vite: specifier: ^6.2.6 - version: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - ../typescript/packages/x402-axios: + ../typescript/packages/http/axios: dependencies: + '@x402/core': + specifier: workspace:^ + version: link:../../core axios: specifier: ^1.7.9 - version: 1.10.0 - viem: - specifier: ^2.21.26 - version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402: - specifier: workspace:^ - version: link:../x402 + version: 1.12.2 zod: specifier: ^3.24.2 version: 3.25.71 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 '@types/node': specifier: ^22.13.4 version: 22.16.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -278,38 +200,41 @@ importers: version: 5.8.3 vite: specifier: ^6.2.6 - version: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - ../typescript/packages/x402-express: + ../typescript/packages/http/express: dependencies: '@coinbase/cdp-sdk': specifier: ^1.22.0 - version: 1.38.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) + version: 1.38.4(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/kit': - specifier: ^5.0.0 - version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - express: - specifier: ^4.18.2 - version: 4.21.2 - viem: - specifier: ^2.21.26 - version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402: + specifier: ^2.1.1 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@x402/core': specifier: workspace:^ - version: link:../x402 + version: link:../../core + '@x402/extensions': + specifier: workspace:^ + version: link:../../extensions + '@x402/paywall': + specifier: workspace:* + version: link:../paywall + viem: + specifier: ^2.39.3 + version: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) zod: specifier: ^3.24.2 version: 3.25.71 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 '@types/express': specifier: ^5.0.1 version: 5.0.3 @@ -318,28 +243,31 @@ importers: version: 22.16.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + express: + specifier: ^4.18.2 + version: 4.21.2 prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -348,56 +276,56 @@ importers: version: 5.8.3 vite: specifier: ^6.2.6 - version: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - ../typescript/packages/x402-fetch: + ../typescript/packages/http/fetch: dependencies: - viem: - specifier: ^2.21.26 - version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402: + '@x402/core': specifier: workspace:^ - version: link:../x402 + version: link:../../core + viem: + specifier: ^2.39.3 + version: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) zod: specifier: ^3.24.2 version: 3.25.71 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 '@types/node': specifier: ^22.13.4 version: 22.16.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -406,65 +334,62 @@ importers: version: 5.8.3 vite: specifier: ^6.2.6 - version: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - ../typescript/packages/x402-hono: + ../typescript/packages/http/hono: dependencies: - '@coinbase/cdp-sdk': - specifier: ^1.22.0 - version: 1.38.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana/kit': - specifier: ^5.0.0 - version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - hono: - specifier: ^4.7.1 - version: 4.8.3 - viem: - specifier: ^2.21.26 - version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402: + '@x402/core': specifier: workspace:^ - version: link:../x402 + version: link:../../core + '@x402/extensions': + specifier: workspace:^ + version: link:../../extensions + '@x402/paywall': + specifier: workspace:* + version: link:../paywall zod: specifier: ^3.24.2 version: 3.25.71 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 '@types/node': specifier: ^22.13.4 version: 22.16.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + hono: + specifier: ^4.7.1 + version: 4.10.2 prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -473,65 +398,65 @@ importers: version: 5.8.3 vite: specifier: ^6.2.6 - version: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - ../typescript/packages/x402-next: + ../typescript/packages/http/next: dependencies: '@coinbase/cdp-sdk': specifier: ^1.22.0 - version: 1.38.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana/kit': - specifier: ^5.0.0 - version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - next: - specifier: ^15.0.0 - version: 15.3.4(react-dom@19.2.1(react@19.2.1))(react@19.2.1) - viem: - specifier: ^2.21.26 - version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402: + version: 1.38.4(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@x402/core': specifier: workspace:^ - version: link:../x402 + version: link:../../core + '@x402/extensions': + specifier: workspace:^ + version: link:../../extensions + '@x402/paywall': + specifier: workspace:* + version: link:../paywall + next: + specifier: ^16.0.7 + version: 16.0.7(react-dom@19.2.1(react@19.2.1))(react@19.2.1) zod: specifier: ^3.24.2 version: 3.25.71 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 '@types/node': specifier: ^22.13.4 version: 22.16.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -540,287 +465,1435 @@ importers: version: 5.8.3 vite: specifier: ^6.2.6 - version: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - clients/axios: + ../typescript/packages/http/paywall: dependencies: - axios: - specifier: ^1.7.9 - version: 1.10.0 - dotenv: - specifier: ^16.5.0 - version: 16.6.1 - viem: - specifier: ^2.21.26 - version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402-axios: + '@scure/base': + specifier: ^1.2.6 + version: 1.2.6 + '@solana-program/compute-budget': + specifier: ^0.8.0 + version: 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token': + specifier: ^0.5.1 + version: 0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token-2022': + specifier: ^0.4.2 + version: 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana/kit': + specifier: ^2.1.1 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': + specifier: ^2.1.1 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/wallet-standard-features': + specifier: ^1.3.0 + version: 1.3.0 + '@tanstack/react-query': + specifier: ^5.90.7 + version: 5.90.8(react@19.2.0) + '@wagmi/connectors': + specifier: ^5.8.1 + version: 5.11.2(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71) + '@wagmi/core': + specifier: ^2.17.1 + version: 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@wallet-standard/app': + specifier: ^1.1.0 + version: 1.1.0 + '@wallet-standard/base': + specifier: ^1.1.0 + version: 1.1.0 + '@wallet-standard/features': + specifier: ^1.1.0 + version: 1.1.0 + '@x402/core': specifier: workspace:* - version: link:../../../typescript/packages/x402-axios + version: link:../../core + viem: + specifier: ^2.39.3 + version: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + wagmi: + specifier: ^2.17.1 + version: 2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) + zod: + specifier: ^3.24.2 + version: 3.25.71 devDependencies: + '@craftamap/esbuild-plugin-html': + specifier: ^0.9.0 + version: 0.9.0(bufferutil@4.0.9)(esbuild@0.25.5)(utf-8-validate@5.0.10) '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 + '@types/node': + specifier: ^22.13.4 + version: 22.16.0 + '@types/react': + specifier: ^19 + version: 19.2.2 + '@types/react-dom': + specifier: ^19 + version: 19.2.2(@types/react@19.2.2) '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@x402/evm': + specifier: workspace:* + version: link:../../mechanisms/evm + '@x402/svm': + specifier: workspace:* + version: link:../../mechanisms/svm + buffer: + specifier: ^6.0.3 + version: 6.0.3 + esbuild: + specifier: ^0.25.4 + version: 0.25.5 eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 + react: + specifier: ^19.0.0 + version: 19.2.0 + react-dom: + specifier: ^19.0.0 + version: 19.2.0(react@19.2.0) + tsup: + specifier: ^8.4.0 + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: - specifier: ^4.7.0 + specifier: ^4.19.2 version: 4.20.3 typescript: - specifier: ^5.3.0 + specifier: ^5.7.3 version: 5.8.3 + vite: + specifier: ^6.2.6 + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - clients/fetch: + ../typescript/packages/legacy/x402: dependencies: - axios: - specifier: ^1.7.9 - version: 1.10.0 - dotenv: - specifier: ^16.4.7 - version: 16.6.1 + '@scure/base': + specifier: ^1.2.6 + version: 1.2.6 + '@solana-program/compute-budget': + specifier: ^0.11.0 + version: 0.11.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token': + specifier: ^0.9.0 + version: 0.9.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token-2022': + specifier: ^0.6.1 + version: 0.6.1(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana/kit': + specifier: ^5.0.0 + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': + specifier: ^5.0.0 + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/wallet-standard-features': + specifier: ^1.3.0 + version: 1.3.0 + '@wallet-standard/app': + specifier: ^1.1.0 + version: 1.1.0 + '@wallet-standard/base': + specifier: ^1.1.0 + version: 1.1.0 + '@wallet-standard/features': + specifier: ^1.1.0 + version: 1.1.0 viem: specifier: ^2.21.26 version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402-fetch: - specifier: workspace:* - version: link:../../../typescript/packages/x402-fetch + wagmi: + specifier: ^2.15.6 + version: 2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) + zod: + specifier: ^3.24.2 + version: 3.25.71 devDependencies: + '@coinbase/onchainkit': + specifier: ^0.38.14 + version: 0.38.19(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(bufferutil@4.0.9)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) + '@craftamap/esbuild-plugin-html': + specifier: ^0.9.0 + version: 0.9.0(bufferutil@4.0.9)(esbuild@0.25.5)(utf-8-validate@5.0.10) '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 + '@types/node': + specifier: ^22.13.4 + version: 22.16.0 + '@types/react': + specifier: ^19 + version: 19.2.2 + '@types/react-dom': + specifier: ^19 + version: 19.2.2(@types/react@19.2.2) '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - eslint: + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@wagmi/connectors': + specifier: ^5.8.1 + version: 5.11.2(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71) + '@wagmi/core': + specifier: ^2.17.1 + version: 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + buffer: + specifier: ^6.0.3 + version: 6.0.3 + esbuild: + specifier: ^0.25.4 + version: 0.25.5 + eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 + react: + specifier: 19.2.1 + version: 19.2.1 + react-dom: + specifier: 19.2.1 + version: 19.2.1(react@19.2.1) + tsup: + specifier: ^8.4.0 + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: - specifier: ^4.7.0 + specifier: ^4.19.2 version: 4.20.3 typescript: - specifier: ^5.3.0 + specifier: ^5.7.3 version: 5.8.3 + vite: + specifier: ^6.2.6 + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - servers/express: + ../typescript/packages/legacy/x402-axios: dependencies: - '@coinbase/x402': - specifier: workspace:* - version: link:../../../typescript/packages/coinbase-x402 - dotenv: - specifier: ^16.6.1 - version: 16.6.1 + axios: + specifier: ^1.7.9 + version: 1.10.0 + viem: + specifier: ^2.21.26 + version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + x402: + specifier: workspace:^ + version: link:../x402 + zod: + specifier: ^3.24.2 + version: 3.25.71 + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@types/node': + specifier: ^22.13.4 + version: 22.16.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^8.4.0 + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) + tsx: + specifier: ^4.19.2 + version: 4.20.3 + typescript: + specifier: ^5.7.3 + version: 5.8.3 + vite: + specifier: ^6.2.6 + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) + + ../typescript/packages/legacy/x402-express: + dependencies: + '@coinbase/cdp-sdk': + specifier: ^1.22.0 + version: 1.38.4(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/kit': + specifier: ^5.0.0 + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) express: specifier: ^4.18.2 version: 4.21.2 - x402-express: - specifier: workspace:* - version: link:../../../typescript/packages/x402-express + viem: + specifier: ^2.21.26 + version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + x402: + specifier: workspace:^ + version: link:../x402 + zod: + specifier: ^3.24.2 + version: 3.25.71 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 '@types/express': specifier: ^5.0.1 version: 5.0.3 + '@types/node': + specifier: ^22.13.4 + version: 22.16.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: - specifier: ^7.2.0 - version: 7.3.0(postcss@8.5.6)(ts-node@10.9.2(@types/node@22.16.0)(typescript@5.8.3))(typescript@5.8.3) + specifier: ^8.4.0 + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: - specifier: ^4.7.0 + specifier: ^4.19.2 version: 4.20.3 typescript: - specifier: ^5.3.0 + specifier: ^5.7.3 version: 5.8.3 + vite: + specifier: ^6.2.6 + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - servers/hono: + ../typescript/packages/legacy/x402-fetch: dependencies: - '@hono/node-server': - specifier: ^1.13.8 - version: 1.15.0(hono@4.8.3) - dotenv: - specifier: ^16.4.7 - version: 16.6.1 + viem: + specifier: ^2.21.26 + version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + x402: + specifier: workspace:^ + version: link:../x402 + zod: + specifier: ^3.24.2 + version: 3.25.71 + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@types/node': + specifier: ^22.13.4 + version: 22.16.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^8.4.0 + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) + tsx: + specifier: ^4.19.2 + version: 4.20.3 + typescript: + specifier: ^5.7.3 + version: 5.8.3 + vite: + specifier: ^6.2.6 + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) + + ../typescript/packages/legacy/x402-hono: + dependencies: + '@coinbase/cdp-sdk': + specifier: ^1.22.0 + version: 1.38.4(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/kit': + specifier: ^5.0.0 + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) hono: specifier: ^4.7.1 - version: 4.8.3 - x402-hono: - specifier: workspace:* - version: link:../../../typescript/packages/x402-hono + version: 4.10.2 + viem: + specifier: ^2.21.26 + version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + x402: + specifier: workspace:^ + version: link:../x402 + zod: + specifier: ^3.24.2 + version: 3.25.71 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 + version: 9.38.0 + '@types/node': + specifier: ^22.13.4 + version: 22.16.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: - specifier: ^7.2.0 - version: 7.3.0(postcss@8.5.6)(ts-node@10.9.2(@types/node@22.16.0)(typescript@5.8.3))(typescript@5.8.3) + specifier: ^8.4.0 + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) tsx: - specifier: ^4.7.0 + specifier: ^4.19.2 version: 4.20.3 typescript: - specifier: ^5.3.0 + specifier: ^5.7.3 version: 5.8.3 + vite: + specifier: ^6.2.6 + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) - servers/next: + ../typescript/packages/legacy/x402-next: dependencies: - '@coinbase/x402': - specifier: workspace:* - version: link:../../../typescript/packages/coinbase-x402 - '@heroicons/react': - specifier: ^2.2.0 - version: 2.2.0(react@19.2.1) + '@coinbase/cdp-sdk': + specifier: ^1.22.0 + version: 1.38.4(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/kit': + specifier: ^5.0.0 + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) next: - specifier: canary - version: 15.4.0-canary.113(@babel/core@7.28.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) - react: - specifier: 19.2.1 - version: 19.2.1 - react-dom: - specifier: 19.2.1 - version: 19.2.1(react@19.2.1) + specifier: ^15.5.7 + version: 15.5.7(@babel/core@7.28.4)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) viem: specifier: ^2.21.26 version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402-next: - specifier: workspace:* - version: link:../../../typescript/packages/x402-next + x402: + specifier: workspace:^ + version: link:../x402 + zod: + specifier: ^3.24.2 + version: 3.25.71 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.30.1 - '@svgr/webpack': - specifier: ^8.1.0 - version: 8.1.0(typescript@5.8.3) + version: 9.38.0 '@types/node': - specifier: ^20 - version: 20.19.4 - '@types/react': - specifier: ^19 - version: 19.1.8 - '@types/react-dom': - specifier: ^19 - version: 19.1.6(@types/react@19.1.8) + specifier: ^22.13.4 + version: 22.16.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - buffer: - specifier: ^6.0.3 - version: 6.0.3 - crypto-browserify: - specifier: ^3.12.1 - version: 3.12.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) eslint: specifier: ^9.24.0 - version: 9.30.1(jiti@1.21.7) - eslint-config-next: - specifier: 15.1.7 - version: 15.1.7(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + version: 9.38.0(jiti@1.21.7) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.30.1(jiti@1.21.7)) + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2) - postcss: - specifier: ^8 - version: 8.5.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 - stream-browserify: - specifier: ^3.0.0 - version: 3.0.0 - tailwindcss: - specifier: ^3.4.1 - version: 3.4.17(ts-node@10.9.2(@types/node@20.19.4)(typescript@5.8.3)) + tsup: + specifier: ^8.4.0 + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) + tsx: + specifier: ^4.19.2 + version: 4.20.3 typescript: - specifier: ^5 + specifier: ^5.7.3 + version: 5.8.3 + vite: + specifier: ^6.2.6 + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) + + ../typescript/packages/mechanisms/evm: + dependencies: + '@x402/core': + specifier: workspace:* + version: link:../../core + viem: + specifier: ^2.39.3 + version: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zod: + specifier: ^3.24.2 + version: 3.25.71 + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@types/node': + specifier: ^22.13.4 + version: 22.16.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^8.4.0 + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) + tsx: + specifier: ^4.19.2 + version: 4.20.3 + typescript: + specifier: ^5.7.3 + version: 5.8.3 + vite: + specifier: ^6.2.6 + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) + + ../typescript/packages/mechanisms/svm: + dependencies: + '@scure/base': + specifier: ^1.2.6 + version: 1.2.6 + '@solana-program/compute-budget': + specifier: ^0.8.0 + version: 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token': + specifier: ^0.5.1 + version: 0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token-2022': + specifier: ^0.4.2 + version: 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana/kit': + specifier: ^2.1.1 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': + specifier: ^2.1.1 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@x402/core': + specifier: workspace:* + version: link:../../core + zod: + specifier: ^3.24.2 + version: 3.25.71 + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@types/node': + specifier: ^22.13.4 + version: 22.16.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^8.4.0 + version: 8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1) + tsx: + specifier: ^4.19.2 + version: 4.20.3 + typescript: + specifier: ^5.7.3 + version: 5.8.3 + vite: + specifier: ^6.2.6 + version: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1) + + clients/axios: + dependencies: + '@scure/base': + specifier: ^1.2.6 + version: 1.2.6 + '@solana/kit': + specifier: ^2.1.1 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@x402/axios': + specifier: workspace:* + version: link:../../../typescript/packages/http/axios + '@x402/core': + specifier: workspace:* + version: link:../../../typescript/packages/core + '@x402/evm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/evm + '@x402/svm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/svm + axios: + specifier: ^1.7.9 + version: 1.12.2 + dotenv: + specifier: ^16.4.7 + version: 16.6.1 + viem: + specifier: ^2.21.26 + version: 2.38.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@4.1.12) + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsx: + specifier: ^4.7.0 + version: 4.20.3 + typescript: + specifier: ^5.3.0 + version: 5.8.3 + + clients/fetch: + dependencies: + '@scure/base': + specifier: ^1.2.6 + version: 1.2.6 + '@solana/kit': + specifier: ^2.1.1 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@x402/core': + specifier: workspace:* + version: link:../../../typescript/packages/core + '@x402/evm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/evm + '@x402/fetch': + specifier: workspace:* + version: link:../../../typescript/packages/http/fetch + '@x402/svm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/svm + axios: + specifier: ^1.7.9 + version: 1.10.0 + dotenv: + specifier: ^16.4.7 + version: 16.6.1 + viem: + specifier: ^2.21.26 + version: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsx: + specifier: ^4.7.0 + version: 4.20.3 + typescript: + specifier: ^5.3.0 + version: 5.8.3 + + facilitators/external-proxies/cdp: + dependencies: + '@coinbase/x402': + specifier: ^0.7.3 + version: 0.7.3(@solana/sysvars@5.0.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@x402/core': + specifier: workspace:* + version: link:../../../../typescript/packages/core + dotenv: + specifier: ^16.4.5 + version: 16.6.1 + express: + specifier: ^4.19.2 + version: 4.21.2 + devDependencies: + '@types/express': + specifier: ^4.17.21 + version: 4.17.23 + '@types/node': + specifier: ^22.10.1 + version: 22.16.0 + eslint: + specifier: ^9.15.0 + version: 9.38.0(jiti@1.21.7) + prettier: + specifier: ^3.3.3 + version: 3.5.2 + tsx: + specifier: ^4.19.2 + version: 4.20.3 + typescript: + specifier: ^5.7.2 + version: 5.8.3 + + facilitators/external-proxies/cdp-dev: + dependencies: + '@coinbase/cdp-sdk': + specifier: ^1.22.0 + version: 1.38.4(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@x402/core': + specifier: workspace:* + version: link:../../../../typescript/packages/core + dotenv: + specifier: ^16.4.5 + version: 16.6.1 + express: + specifier: ^4.19.2 + version: 4.21.2 + devDependencies: + '@types/express': + specifier: ^4.17.21 + version: 4.17.23 + '@types/node': + specifier: ^22.10.1 + version: 22.16.0 + eslint: + specifier: ^9.15.0 + version: 9.38.0(jiti@1.21.7) + prettier: + specifier: ^3.3.3 + version: 3.5.2 + tsx: + specifier: ^4.19.2 + version: 4.20.3 + typescript: + specifier: ^5.7.2 + version: 5.8.3 + x402: + specifier: workspace:* + version: link:../../../../typescript/packages/legacy/x402 + + facilitators/typescript: + dependencies: + '@scure/base': + specifier: ^1.2.6 + version: 1.2.6 + '@solana/kit': + specifier: ^2.1.1 + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@x402/core': + specifier: workspace:* + version: link:../../../typescript/packages/core + '@x402/evm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/evm + '@x402/extensions': + specifier: workspace:* + version: link:../../../typescript/packages/extensions + '@x402/svm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/svm + dotenv: + specifier: ^16.4.5 + version: 16.6.1 + express: + specifier: ^4.19.2 + version: 4.21.2 + viem: + specifier: ^2.21.54 + version: 2.38.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@4.1.12) + devDependencies: + '@types/express': + specifier: ^4.17.21 + version: 4.17.23 + '@types/node': + specifier: ^22.10.1 + version: 22.16.0 + eslint: + specifier: ^9.15.0 + version: 9.38.0(jiti@1.21.7) + prettier: + specifier: ^3.3.3 + version: 3.5.2 + tsx: + specifier: ^4.19.2 + version: 4.20.3 + typescript: + specifier: ^5.7.2 + version: 5.8.3 + + legacy/clients/axios: + dependencies: + axios: + specifier: ^1.7.9 + version: 1.12.2 + dotenv: + specifier: ^16.5.0 + version: 16.6.1 + viem: + specifier: ^2.21.26 + version: 2.38.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@4.1.12) + x402-axios: + specifier: workspace:* + version: link:../../../../typescript/packages/legacy/x402-axios + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsx: + specifier: ^4.7.0 + version: 4.20.3 + typescript: + specifier: ^5.3.0 + version: 5.8.3 + + legacy/clients/fetch: + dependencies: + axios: + specifier: ^1.7.9 + version: 1.12.2 + dotenv: + specifier: ^16.4.7 + version: 16.6.1 + viem: + specifier: ^2.21.26 + version: 2.38.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@4.1.12) + x402-fetch: + specifier: workspace:* + version: link:../../../../typescript/packages/legacy/x402-fetch + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsx: + specifier: ^4.7.0 + version: 4.20.3 + typescript: + specifier: ^5.3.0 + version: 5.8.3 + + legacy/servers/express: + dependencies: + dotenv: + specifier: ^16.6.1 + version: 16.6.1 + express: + specifier: ^4.18.2 + version: 4.21.2 + x402-express: + specifier: workspace:* + version: link:../../../../typescript/packages/legacy/x402-express + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@types/express': + specifier: ^5.0.1 + version: 5.0.3 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^7.2.0 + version: 7.3.0(postcss@8.5.6)(typescript@5.8.3) + tsx: + specifier: ^4.7.0 + version: 4.20.3 + typescript: + specifier: ^5.3.0 + version: 5.8.3 + + legacy/servers/hono: + dependencies: + '@hono/node-server': + specifier: ^1.13.8 + version: 1.19.5(hono@4.10.2) + dotenv: + specifier: ^16.4.7 + version: 16.6.1 + hono: + specifier: ^4.7.1 + version: 4.10.2 + x402-hono: + specifier: workspace:* + version: link:../../../../typescript/packages/legacy/x402-hono + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^7.2.0 + version: 7.3.0(postcss@8.5.6)(typescript@5.8.3) + tsx: + specifier: ^4.7.0 + version: 4.20.3 + typescript: + specifier: ^5.3.0 + version: 5.8.3 + + legacy/servers/next: + dependencies: + '@heroicons/react': + specifier: ^2.2.0 + version: 2.2.0(react@19.2.1) + next: + specifier: ^15.5.7 + version: 15.5.7(@babel/core@7.28.4)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + react: + specifier: 19.2.1 + version: 19.2.1 + react-dom: + specifier: 19.2.1 + version: 19.2.1(react@19.2.1) + viem: + specifier: ^2.21.26 + version: 2.38.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@4.1.12) + x402-next: + specifier: workspace:* + version: link:../../../../typescript/packages/legacy/x402-next + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@svgr/webpack': + specifier: ^8.1.0 + version: 8.1.0(typescript@5.8.3) + '@types/node': + specifier: ^20 + version: 20.19.4 + '@types/react': + specifier: ^19 + version: 19.2.2 + '@types/react-dom': + specifier: ^19 + version: 19.2.2(@types/react@19.2.2) + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + buffer: + specifier: ^6.0.3 + version: 6.0.3 + crypto-browserify: + specifier: ^3.12.1 + version: 3.12.1 + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-config-next: + specifier: 15.1.9 + version: 15.1.9(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + postcss: + specifier: ^8 + version: 8.5.6 + prettier: + specifier: 3.5.2 + version: 3.5.2 + stream-browserify: + specifier: ^3.0.0 + version: 3.0.0 + tailwindcss: + specifier: ^3.4.1 + version: 3.4.18(tsx@4.20.3)(yaml@2.8.1) + typescript: + specifier: ^5 + version: 5.8.3 + + servers/express: + dependencies: + '@x402/core': + specifier: workspace:* + version: link:../../../typescript/packages/core + '@x402/evm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/evm + '@x402/express': + specifier: workspace:* + version: link:../../../typescript/packages/http/express + '@x402/extensions': + specifier: workspace:* + version: link:../../../typescript/packages/extensions + '@x402/svm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/svm + dotenv: + specifier: ^16.6.1 + version: 16.6.1 + express: + specifier: ^4.18.2 + version: 4.21.2 + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@types/express': + specifier: ^5.0.1 + version: 5.0.3 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^7.2.0 + version: 7.3.0(postcss@8.5.6)(typescript@5.8.3) + tsx: + specifier: ^4.7.0 + version: 4.20.3 + typescript: + specifier: ^5.3.0 + version: 5.8.3 + + servers/hono: + dependencies: + '@hono/node-server': + specifier: ^1.14.0 + version: 1.19.5(hono@4.10.2) + '@x402/core': + specifier: workspace:* + version: link:../../../typescript/packages/core + '@x402/evm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/evm + '@x402/extensions': + specifier: workspace:* + version: link:../../../typescript/packages/extensions + '@x402/hono': + specifier: workspace:* + version: link:../../../typescript/packages/http/hono + '@x402/svm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/svm + dotenv: + specifier: ^16.6.1 + version: 16.6.1 + hono: + specifier: ^4.7.1 + version: 4.10.2 + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@types/express': + specifier: ^5.0.1 + version: 5.0.3 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^7.2.0 + version: 7.3.0(postcss@8.5.6)(typescript@5.8.3) + tsx: + specifier: ^4.7.0 + version: 4.20.3 + typescript: + specifier: ^5.3.0 + version: 5.8.3 + + servers/next: + dependencies: + '@heroicons/react': + specifier: ^2.2.0 + version: 2.2.0(react@19.2.1) + '@x402/core': + specifier: workspace:* + version: link:../../../typescript/packages/core + '@x402/evm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/evm + '@x402/extensions': + specifier: workspace:* + version: link:../../../typescript/packages/extensions + '@x402/next': + specifier: workspace:* + version: link:../../../typescript/packages/http/next + '@x402/svm': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/svm + next: + specifier: ^16.0.7 + version: 16.0.7(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + react: + specifier: ^19.2.1 + version: 19.2.1 + react-dom: + specifier: ^19.2.1 + version: 19.2.1(react@19.2.1) + viem: + specifier: ^2.21.26 + version: 2.38.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.38.0 + '@types/node': + specifier: ^20 + version: 20.19.4 + '@types/react': + specifier: ^19 + version: 19.2.2 + '@types/react-dom': + specifier: ^19 + version: 19.2.2(@types/react@19.2.2) + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + buffer: + specifier: ^6.0.3 + version: 6.0.3 + crypto-browserify: + specifier: ^3.12.1 + version: 3.12.1 + eslint: + specifier: ^9.24.0 + version: 9.38.0(jiti@1.21.7) + eslint-config-next: + specifier: 16.0.7 + version: 16.0.7(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2) + postcss: + specifier: ^8 + version: 8.5.6 + prettier: + specifier: 3.5.2 + version: 3.5.2 + stream-browserify: + specifier: ^3.0.0 + version: 3.0.0 + tailwindcss: + specifier: ^3.4.1 + version: 3.4.18(tsx@4.20.3)(yaml@2.8.1) + typescript: + specifier: ^5 version: 5.8.3 packages: @@ -832,10 +1905,6 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} @@ -843,16 +1912,16 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.0': - resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} + '@babel/compat-data@7.28.4': + resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.0': - resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==} + '@babel/core@7.28.4': + resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.0': - resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} + '@babel/generator@7.28.3': + resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.27.3': @@ -863,8 +1932,8 @@ packages: resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.27.1': - resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==} + '@babel/helper-create-class-features-plugin@7.28.3': + resolution: {integrity: sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -892,8 +1961,8 @@ packages: resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.27.3': - resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -934,16 +2003,16 @@ packages: resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.27.1': - resolution: {integrity: sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==} + '@babel/helper-wrap-function@7.28.3': + resolution: {integrity: sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.27.6': - resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.0': - resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} + '@babel/parser@7.28.4': + resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} engines: {node: '>=6.0.0'} hasBin: true @@ -971,8 +2040,8 @@ packages: peerDependencies: '@babel/core': ^7.13.0 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1': - resolution: {integrity: sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3': + resolution: {integrity: sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1037,8 +2106,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.28.0': - resolution: {integrity: sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==} + '@babel/plugin-transform-block-scoping@7.28.4': + resolution: {integrity: sha512-1yxmvN0MJHOhPVmAsmoW5liWwoILobu/d/ShymZmj867bAdxGbehIrew1DuLpw2Ukv+qDSSPQdYW1dLNE7t11A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1049,14 +2118,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.27.1': - resolution: {integrity: sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==} + '@babel/plugin-transform-class-static-block@7.28.3': + resolution: {integrity: sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 - '@babel/plugin-transform-classes@7.28.0': - resolution: {integrity: sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==} + '@babel/plugin-transform-classes@7.28.4': + resolution: {integrity: sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1199,8 +2268,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.28.0': - resolution: {integrity: sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==} + '@babel/plugin-transform-object-rest-spread@7.28.4': + resolution: {integrity: sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1277,8 +2346,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.28.0': - resolution: {integrity: sha512-LOAozRVbqxEVjSKfhGnuLoE4Kz4Oc5UJzuvFUhSsQzdCdaAQu06mG8zDv2GFSerM62nImUZ7K92vxnQcLSDlCQ==} + '@babel/plugin-transform-regenerator@7.28.4': + resolution: {integrity: sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1355,8 +2424,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.28.0': - resolution: {integrity: sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg==} + '@babel/preset-env@7.28.3': + resolution: {integrity: sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1378,27 +2447,30 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.27.6': - resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==} + '@babel/runtime@7.28.4': + resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.0': - resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} + '@babel/traverse@7.28.4': + resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.0': - resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==} + '@babel/types@7.28.4': + resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} engines: {node: '>=6.9.0'} - '@coinbase/cdp-sdk@1.38.0': - resolution: {integrity: sha512-q9DVmzTqhS0WFuU/IfSahp0wvdy2CAwftl2f110z90w5BHLFhUlK9OKFmIuZMZ3dCo6GK6IWq0IlQERdezruSg==} + '@base-org/account@1.1.1': + resolution: {integrity: sha512-IfVJPrDPhHfqXRDb89472hXkpvJuQQR7FDI9isLPHEqSYt/45whIoBxSPgZ0ssTt379VhQo4+87PWI1DoLSfAQ==} - '@coinbase/onchainkit@0.38.15': - resolution: {integrity: sha512-RlZ2I7XlNyuVaWjF7/1WY6LzQTaRH2bTitb1wfwTEfxM8a1matfitpNZ2vAVLjRqDvHvgzegfyW6xxS+dUuCxA==} + '@coinbase/cdp-sdk@1.38.4': + resolution: {integrity: sha512-xVvfluaGt0NxNmjElP3C1yI6KnsGwihabdXj+qNtjjsSmd/Ha2V3gAiCyNrrYOqIORn4mpC2jgu2fUFEDaMpaw==} + + '@coinbase/onchainkit@0.38.19': + resolution: {integrity: sha512-4uiujoTO5/8/dpWVZoTlBC7z0Y1N5fgBYDR6pKN/r6a8pX83ObUuOSGhSzJ8Xbu8NpPU6TXX+VuzLiwiLg/irg==} peerDependencies: react: ^18 || ^19 react-dom: ^18 || ^19 @@ -1406,8 +2478,11 @@ packages: '@coinbase/wallet-sdk@3.9.3': resolution: {integrity: sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw==} - '@coinbase/wallet-sdk@4.3.3': - resolution: {integrity: sha512-h8gMLQNvP5TIJVXFOyQZaxbi1Mg5alFR4Z2/PEIngdyXZEoQGcVhzyQGuDa3t9zpllxvqfAaKfzDhsfCo+nhSQ==} + '@coinbase/wallet-sdk@4.3.6': + resolution: {integrity: sha512-4q8BNG1ViL4mSAAvPAtpwlOs1gpC+67eQtgIwNvT3xyeyFFd+guwkc8bcX5rTmQhXpqnhzC4f0obACbP9CqMSA==} + + '@coinbase/x402@0.7.3': + resolution: {integrity: sha512-mSxxbPnDCvSLfq6ZZAB5P1HyYQfQNSdWyY01Cn7yjzTuGUFFgZ7onDkbZnZ1Yry0UnG467aqrmjs6AgoYgpzCQ==} '@craftamap/esbuild-plugin-html@0.9.0': resolution: {integrity: sha512-V5LFrcGXQWU1SSzYPwxEFjF8IjeXW0oTKh5c0xyhGuTNoEnjgJRNSX83HnZ5TTAutJfo/MAyWA4Z9/fIwbMhUQ==} @@ -1415,12 +2490,8 @@ packages: peerDependencies: esbuild: '>=0.15.10' - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - - '@csstools/color-helpers@5.0.2': - resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} engines: {node: '>=18'} '@csstools/css-calc@2.1.4': @@ -1430,8 +2501,8 @@ packages: '@csstools/css-parser-algorithms': ^3.0.5 '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-color-parser@3.0.10': - resolution: {integrity: sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==} + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} engines: {node: '>=18'} peerDependencies: '@csstools/css-parser-algorithms': ^3.0.5 @@ -1447,20 +2518,20 @@ packages: resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} - '@ecies/ciphers@0.2.3': - resolution: {integrity: sha512-tapn6XhOueMwht3E2UzY0ZZjYokdaw9XtL9kEyjhQ/Fb9vL9xTFbOaI+fV0AWvTpYu4BNloC6getKW6NtSg4mA==} + '@ecies/ciphers@0.2.4': + resolution: {integrity: sha512-t+iX+Wf5nRKyNzk8dviW3Ikb/280+aEJAnw9YXvCp2tYGPSkMki+NRY+8aNLmVFv3eNtMdvViPNOPxS8SZNP+w==} engines: {bun: '>=1', deno: '>=2', node: '>=16'} peerDependencies: '@noble/ciphers': ^1.0.0 - '@emnapi/core@1.4.3': - resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} + '@emnapi/core@1.6.0': + resolution: {integrity: sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg==} - '@emnapi/runtime@1.4.3': - resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + '@emnapi/runtime@1.6.0': + resolution: {integrity: sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==} - '@emnapi/wasi-threads@1.0.2': - resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} '@es-joy/jsdoccomment@0.50.2': resolution: {integrity: sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA==} @@ -1754,46 +2825,42 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.7.0': - resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.21.0': - resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.3.0': - resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} + '@eslint/config-helpers@0.4.1': + resolution: {integrity: sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.14.0': - resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.15.1': - resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==} + '@eslint/core@0.16.0': + resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.30.1': - resolution: {integrity: sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==} + '@eslint/js@9.38.0': + resolution: {integrity: sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.6': - resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.3.3': - resolution: {integrity: sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==} + '@eslint/plugin-kit@0.4.0': + resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ethereumjs/common@3.2.0': @@ -1812,24 +2879,38 @@ packages: resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} engines: {node: '>=14'} - '@farcaster/frame-core@0.1.8': - resolution: {integrity: sha512-Y0JATQXa/iaqH3pCp8Dby4iCQbwqw7JJaGtfzUazdr7R+zs3EDP8DYQCkqJu6iGjE9gqgecB+b+DOZpnqMTDNw==} + '@farcaster/frame-sdk@0.1.12': + resolution: {integrity: sha512-qlikvkxsrsvKGutr3PM3Yvsuni2Fku15aPagrCyHZWbYAJrZ4mRJM6u9S8eLAXMMnYd9gJ9yor6COYgmZMBOgQ==} + engines: {node: '>=22.11.0'} - '@farcaster/frame-sdk@0.0.60': - resolution: {integrity: sha512-MHQwdFT1VPe3kS0NvnORBPb/DQXr8qpdSDgIgfrdVCB8byQ5uFELlr3gQMuFYFyLFQVXgbMl75z8O6+hvorqow==} + '@farcaster/miniapp-core@0.4.1': + resolution: {integrity: sha512-20FxHTRToYUKx7CQ8PvIy9OoQ6XjdmF1pRMS7dsj37qdqjVDeEkYoK8yXwnoReZoJRcYwIg8P3i6V8bTWNR5mg==} - '@farcaster/frame-wagmi-connector@0.0.53': - resolution: {integrity: sha512-+fonXzzj3KxTeUHbtt7lZUC4v/MhC2Y2KpQw7WcVamiDwedm+jTMqBIdrMrWRej/HSWrBQ1rDIOlsWxnv9CDng==} + '@farcaster/miniapp-sdk@0.2.1': + resolution: {integrity: sha512-2SnDeOtDdlN1lGQt7UyH2jkrZRQDOkmhcrlzNWazYChyPh9XfV8+9fMS+Lr/E2pEws9Q40Xl9POrCzdpUC19lg==} + + '@farcaster/miniapp-wagmi-connector@1.1.0': + resolution: {integrity: sha512-gf0nDx9nNJ6hJXbFBCgiTitb0eEqBvCU/njcyTXf7ebZhT0pzOrarOod2dkeisU5Py+WWjFyOVcqmeo4G3IvDA==} peerDependencies: - '@farcaster/frame-sdk': ^0.0.64 + '@farcaster/miniapp-sdk': ^0.2.0 '@wagmi/core': ^2.14.1 viem: ^2.21.55 - '@farcaster/quick-auth@0.0.5': - resolution: {integrity: sha512-Z8hWz/7c33zlmII2AJHja/Wz0C03mm2o+CEBtBylmiun1wC4FMgx1Fal699VQvBUG1lpcJ662WxuRNxKogktDw==} + '@farcaster/quick-auth@0.0.6': + resolution: {integrity: sha512-tiZndhpfDtEhaKlkmS5cVDuS+A/tafqZT3y9I44rC69m3beJok6e8dIH2JhxVy3EvOWTyTBnrmNn6GOOh+qK6A==} + peerDependencies: + typescript: 5.8.3 + + '@farcaster/quick-auth@0.0.8': + resolution: {integrity: sha512-NRIq1BcbcQCC6xBF5owfckkY00xKQVpqhpLNl5rICVpl0xeDsiVbkenIrHaUuyjtCK2W28YVc2ZCFRyz9ERHKg==} peerDependencies: typescript: 5.8.3 + '@gemini-wallet/core@0.2.0': + resolution: {integrity: sha512-vv9aozWnKrrPWQ3vIFcWk7yta4hQW1Ie0fsNNPeXnjAxkbXr2hqMagEptLuMxpEP2W3mnRu05VDNKzcvAuuZDw==} + peerDependencies: + viem: '>=2.0.0' + '@graphql-typed-document-node/core@3.2.0': resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} peerDependencies: @@ -1840,8 +2921,8 @@ packages: peerDependencies: react: '>= 16 || ^19.0.0-rc' - '@hono/node-server@1.15.0': - resolution: {integrity: sha512-MjmK4l5N4dQpZ9OSWN0tCj7ejuc7WvuWMzSKtc89bnknJykAeHxzRigXBTYZk85H6Awrii6RM59iUiUluApu2A==} + '@hono/node-server@1.19.5': + resolution: {integrity: sha512-iBuhh+uaaggeAuf+TftcjZyWh2GEgZcVGXkNtskLVoWaXhnJtC5HLHrU8W1KHDoucqO1MswwglmkWLFyiDn4WQ==} engines: {node: '>=18.14.1'} peerDependencies: hono: ^4 @@ -1850,134 +2931,140 @@ packages: resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - '@humanwhocodes/retry@0.4.3': resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@img/sharp-darwin-arm64@0.34.2': - resolution: {integrity: sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==} + '@img/colour@1.0.0': + resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.4': + resolution: {integrity: sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.34.2': - resolution: {integrity: sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==} + '@img/sharp-darwin-x64@0.34.4': + resolution: {integrity: sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] - '@img/sharp-libvips-darwin-arm64@1.1.0': - resolution: {integrity: sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==} + '@img/sharp-libvips-darwin-arm64@1.2.3': + resolution: {integrity: sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==} cpu: [arm64] os: [darwin] - '@img/sharp-libvips-darwin-x64@1.1.0': - resolution: {integrity: sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==} + '@img/sharp-libvips-darwin-x64@1.2.3': + resolution: {integrity: sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==} cpu: [x64] os: [darwin] - '@img/sharp-libvips-linux-arm64@1.1.0': - resolution: {integrity: sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==} + '@img/sharp-libvips-linux-arm64@1.2.3': + resolution: {integrity: sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linux-arm@1.1.0': - resolution: {integrity: sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==} + '@img/sharp-libvips-linux-arm@1.2.3': + resolution: {integrity: sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==} cpu: [arm] os: [linux] - '@img/sharp-libvips-linux-ppc64@1.1.0': - resolution: {integrity: sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==} + '@img/sharp-libvips-linux-ppc64@1.2.3': + resolution: {integrity: sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==} cpu: [ppc64] os: [linux] - '@img/sharp-libvips-linux-s390x@1.1.0': - resolution: {integrity: sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==} + '@img/sharp-libvips-linux-s390x@1.2.3': + resolution: {integrity: sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==} cpu: [s390x] os: [linux] - '@img/sharp-libvips-linux-x64@1.1.0': - resolution: {integrity: sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==} + '@img/sharp-libvips-linux-x64@1.2.3': + resolution: {integrity: sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==} cpu: [x64] os: [linux] - '@img/sharp-libvips-linuxmusl-arm64@1.1.0': - resolution: {integrity: sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==} + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': + resolution: {integrity: sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linuxmusl-x64@1.1.0': - resolution: {integrity: sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==} + '@img/sharp-libvips-linuxmusl-x64@1.2.3': + resolution: {integrity: sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==} cpu: [x64] os: [linux] - '@img/sharp-linux-arm64@0.34.2': - resolution: {integrity: sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==} + '@img/sharp-linux-arm64@0.34.4': + resolution: {integrity: sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linux-arm@0.34.2': - resolution: {integrity: sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==} + '@img/sharp-linux-arm@0.34.4': + resolution: {integrity: sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - '@img/sharp-linux-s390x@0.34.2': - resolution: {integrity: sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==} + '@img/sharp-linux-ppc64@0.34.4': + resolution: {integrity: sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.4': + resolution: {integrity: sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - '@img/sharp-linux-x64@0.34.2': - resolution: {integrity: sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==} + '@img/sharp-linux-x64@0.34.4': + resolution: {integrity: sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-linuxmusl-arm64@0.34.2': - resolution: {integrity: sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==} + '@img/sharp-linuxmusl-arm64@0.34.4': + resolution: {integrity: sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linuxmusl-x64@0.34.2': - resolution: {integrity: sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==} + '@img/sharp-linuxmusl-x64@0.34.4': + resolution: {integrity: sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-wasm32@0.34.2': - resolution: {integrity: sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==} + '@img/sharp-wasm32@0.34.4': + resolution: {integrity: sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] - '@img/sharp-win32-arm64@0.34.2': - resolution: {integrity: sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==} + '@img/sharp-win32-arm64@0.34.4': + resolution: {integrity: sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [win32] - '@img/sharp-win32-ia32@0.34.2': - resolution: {integrity: sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==} + '@img/sharp-win32-ia32@0.34.4': + resolution: {integrity: sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.34.2': - resolution: {integrity: sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==} + '@img/sharp-win32-x64@0.34.4': + resolution: {integrity: sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] @@ -1986,27 +3073,27 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - '@jridgewell/gen-mapping@0.3.12': - resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.4': - resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} - - '@jridgewell/trace-mapping@0.3.29': - resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@lit-labs/ssr-dom-shim@1.3.0': - resolution: {integrity: sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==} + '@lit-labs/ssr-dom-shim@1.4.0': + resolution: {integrity: sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==} - '@lit/reactive-element@2.1.0': - resolution: {integrity: sha512-L2qyoZSQClcBmq0qajBVbhYEcG6iK0XfLn66ifLe/RfC0/ihpc+pl0Wdn8bJ8o+hj38cG0fGXRgSS20MuXn7qA==} + '@lit/reactive-element@2.1.1': + resolution: {integrity: sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==} '@metamask/eth-json-rpc-provider@1.0.1': resolution: {integrity: sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==} @@ -2039,6 +3126,10 @@ packages: resolution: {integrity: sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==} engines: {node: '>=16.0.0'} + '@metamask/rpc-errors@7.0.2': + resolution: {integrity: sha512-YYYHsVYd46XwY2QZzpGeU4PSdRhHdxnzkB8piWGvJW2xbikZ3R+epAYEL4q/K8bh9JPTucsUdwRFnACor1aOYw==} + engines: {node: ^18.20 || ^20.17 || >=22} + '@metamask/safe-event-emitter@2.0.0': resolution: {integrity: sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==} @@ -2046,8 +3137,11 @@ packages: resolution: {integrity: sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==} engines: {node: '>=12.0.0'} - '@metamask/sdk-communication-layer@0.32.0': - resolution: {integrity: sha512-dmj/KFjMi1fsdZGIOtbhxdg3amxhKL/A5BqSU4uh/SyDKPub/OT+x5pX8bGjpTL1WPWY/Q0OIlvFyX3VWnT06Q==} + '@metamask/sdk-analytics@0.0.5': + resolution: {integrity: sha512-fDah+keS1RjSUlC8GmYXvx6Y26s3Ax1U9hGpWb6GSY5SAdmTSIqp2CvYy6yW0WgLhnYhW+6xERuD0eVqV63QIQ==} + + '@metamask/sdk-communication-layer@0.33.1': + resolution: {integrity: sha512-0bI9hkysxcfbZ/lk0T2+aKVo1j0ynQVTuB3sJ5ssPWlz+Z3VwveCkP1O7EVu1tsVVCb0YV5WxK9zmURu2FIiaA==} peerDependencies: cross-fetch: ^4.0.0 eciesjs: '*' @@ -2055,16 +3149,20 @@ packages: readable-stream: ^3.6.2 socket.io-client: ^4.5.1 - '@metamask/sdk-install-modal-web@0.32.0': - resolution: {integrity: sha512-TFoktj0JgfWnQaL3yFkApqNwcaqJ+dw4xcnrJueMP3aXkSNev2Ido+WVNOg4IIMxnmOrfAC9t0UJ0u/dC9MjOQ==} + '@metamask/sdk-install-modal-web@0.32.1': + resolution: {integrity: sha512-MGmAo6qSjf1tuYXhCu2EZLftq+DSt5Z7fsIKr2P+lDgdTPWgLfZB1tJKzNcwKKOdf6q9Qmmxn7lJuI/gq5LrKw==} - '@metamask/sdk@0.32.0': - resolution: {integrity: sha512-WmGAlP1oBuD9hk4CsdlG1WJFuPtYJY+dnTHJMeCyohTWD2GgkcLMUUuvu9lO1/NVzuOoSi1OrnjbuY1O/1NZ1g==} + '@metamask/sdk@0.33.1': + resolution: {integrity: sha512-1mcOQVGr9rSrVcbKPNVzbZ8eCl1K0FATsYH3WJ/MH4WcZDWGECWrXJPNMZoEAkLxWiMe8jOQBumg2pmcDa9zpQ==} '@metamask/superstruct@3.2.1': resolution: {integrity: sha512-fLgJnDOXFmuVlB38rUN5SmU7hAFQcCjrg3Vrxz67KTY7YHFnSNEKvX4avmEBdOI0yTCxZjwMCFEqsC8k2+Wd3g==} engines: {node: '>=16.0.0'} + '@metamask/utils@11.8.1': + resolution: {integrity: sha512-DIbsNUyqWLFgqJlZxi1OOCMYvI23GqFCvNJAtzv8/WXWzJfnJnvp1M24j7VvUe3URBi3S86UgQ7+7aWU9p/cnQ==} + engines: {node: ^18.18 || ^20.14 || >=22} + '@metamask/utils@5.0.2': resolution: {integrity: sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==} engines: {node: '>=14.0.0'} @@ -2077,110 +3175,113 @@ packages: resolution: {integrity: sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==} engines: {node: '>=16.0.0'} - '@napi-rs/wasm-runtime@0.2.11': - resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==} + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + + '@next/env@15.5.7': + resolution: {integrity: sha512-4h6Y2NyEkIEN7Z8YxkA27pq6zTkS09bUSYC0xjd0NpwFxjnIKeZEeH591o5WECSmjpUhLn3H2QLJcDye3Uzcvg==} - '@next/env@15.3.4': - resolution: {integrity: sha512-ZkdYzBseS6UjYzz6ylVKPOK+//zLWvD6Ta+vpoye8cW11AjiQjGYVibF0xuvT4L0iJfAPfZLFidaEzAOywyOAQ==} + '@next/env@16.0.7': + resolution: {integrity: sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw==} - '@next/env@15.4.0-canary.113': - resolution: {integrity: sha512-+HC7oDcADo3Xh4luInUBRv8x96fHh0vDjcsUN8ecZRcd+2gc37CgRcdYJofWnLnIbEsuIV6U8LwYYhJRw9N1nw==} + '@next/eslint-plugin-next@15.1.9': + resolution: {integrity: sha512-H7CuatO2RXQQmm40cX3C6kFPNh/v6Dx2oEy1iKZKfubL0mhuuDMBLSUdwu5JgCP1mtuPBufK1h7WSIVjBADZtw==} - '@next/eslint-plugin-next@15.1.7': - resolution: {integrity: sha512-kRP7RjSxfTO13NE317ek3mSGzoZlI33nc/i5hs1KaWpK+egs85xg0DJ4p32QEiHnR0mVjuUfhRIun7awqfL7pQ==} + '@next/eslint-plugin-next@16.0.7': + resolution: {integrity: sha512-hFrTNZcMEG+k7qxVxZJq3F32Kms130FAhG8lvw2zkKBgAcNOJIxlljNiCjGygvBshvaGBdf88q2CqWtnqezDHA==} - '@next/swc-darwin-arm64@15.3.4': - resolution: {integrity: sha512-z0qIYTONmPRbwHWvpyrFXJd5F9YWLCsw3Sjrzj2ZvMYy9NPQMPZ1NjOJh4ojr4oQzcGYwgJKfidzehaNa1BpEg==} + '@next/swc-darwin-arm64@15.5.7': + resolution: {integrity: sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-arm64@15.4.0-canary.113': - resolution: {integrity: sha512-Rug3HXDrkjlfrIiREBwWjC3DWHWeSjHDYcWjjwnsj5jlUH+HTzyJCa1mSQR3vYiR8cES1CmLhYW5ELVyrDIoMw==} + '@next/swc-darwin-arm64@16.0.7': + resolution: {integrity: sha512-LlDtCYOEj/rfSnEn/Idi+j1QKHxY9BJFmxx7108A6D8K0SB+bNgfYQATPk/4LqOl4C0Wo3LACg2ie6s7xqMpJg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.3.4': - resolution: {integrity: sha512-Z0FYJM8lritw5Wq+vpHYuCIzIlEMjewG2aRkc3Hi2rcbULknYL/xqfpBL23jQnCSrDUGAo/AEv0Z+s2bff9Zkw==} + '@next/swc-darwin-x64@15.5.7': + resolution: {integrity: sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-darwin-x64@15.4.0-canary.113': - resolution: {integrity: sha512-djM2ai6MYbcop28H0y2VKucmdSvoaVWrA5N8eZ1SlMdwqfIaBeihosr5MFahqMRS3MKe43Cny6bgdJ3WAIhTDA==} + '@next/swc-darwin-x64@16.0.7': + resolution: {integrity: sha512-rtZ7BhnVvO1ICf3QzfW9H3aPz7GhBrnSIMZyr4Qy6boXF0b5E3QLs+cvJmg3PsTCG2M1PBoC+DANUi4wCOKXpA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.3.4': - resolution: {integrity: sha512-l8ZQOCCg7adwmsnFm8m5q9eIPAHdaB2F3cxhufYtVo84pymwKuWfpYTKcUiFcutJdp9xGHC+F1Uq3xnFU1B/7g==} + '@next/swc-linux-arm64-gnu@15.5.7': + resolution: {integrity: sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-gnu@15.4.0-canary.113': - resolution: {integrity: sha512-LPAX6qvaZEhkws1Vg8KL/KJPs2NqepaoqvEa+9iqqKWAx16Pz0nmerNo7A1pSws+6IP4YDrc6qGxznpZXRyQiA==} + '@next/swc-linux-arm64-gnu@16.0.7': + resolution: {integrity: sha512-mloD5WcPIeIeeZqAIP5c2kdaTa6StwP4/2EGy1mUw8HiexSHGK/jcM7lFuS3u3i2zn+xH9+wXJs6njO7VrAqww==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.3.4': - resolution: {integrity: sha512-wFyZ7X470YJQtpKot4xCY3gpdn8lE9nTlldG07/kJYexCUpX1piX+MBfZdvulo+t1yADFVEuzFfVHfklfEx8kw==} + '@next/swc-linux-arm64-musl@15.5.7': + resolution: {integrity: sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.4.0-canary.113': - resolution: {integrity: sha512-8/a0Fb41O0ArrMIuo20v5iS3e9j602eUPNLtOjrJImyQ0SLRL5N8BYlz6LTW56cYJcNVl/8MLfZY1fTz7n157w==} + '@next/swc-linux-arm64-musl@16.0.7': + resolution: {integrity: sha512-+ksWNrZrthisXuo9gd1XnjHRowCbMtl/YgMpbRvFeDEqEBd523YHPWpBuDjomod88U8Xliw5DHhekBC3EOOd9g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.3.4': - resolution: {integrity: sha512-gEbH9rv9o7I12qPyvZNVTyP/PWKqOp8clvnoYZQiX800KkqsaJZuOXkWgMa7ANCCh/oEN2ZQheh3yH8/kWPSEg==} + '@next/swc-linux-x64-gnu@15.5.7': + resolution: {integrity: sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-gnu@15.4.0-canary.113': - resolution: {integrity: sha512-Ubil9yLdDRmVwRXsbczSeQPGaH5Wgqa2I7l4nJsgzdvJcdcVEH/0MRNy1MIGQXfnB5mLofZ7YFDWaL/yTdDP2Q==} + '@next/swc-linux-x64-gnu@16.0.7': + resolution: {integrity: sha512-4WtJU5cRDxpEE44Ana2Xro1284hnyVpBb62lIpU5k85D8xXxatT+rXxBgPkc7C1XwkZMWpK5rXLXTh9PFipWsA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.3.4': - resolution: {integrity: sha512-Cf8sr0ufuC/nu/yQ76AnarbSAXcwG/wj+1xFPNbyNo8ltA6kw5d5YqO8kQuwVIxk13SBdtgXrNyom3ZosHAy4A==} + '@next/swc-linux-x64-musl@15.5.7': + resolution: {integrity: sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.4.0-canary.113': - resolution: {integrity: sha512-EhPvX+yqDKGwVaTQuosGujUZy1cjbIuZ+FU4obu4hFjgjrlps9nxoS6vM/wHXitzN1hdfg0HiUsFOl3KZWd4fw==} + '@next/swc-linux-x64-musl@16.0.7': + resolution: {integrity: sha512-HYlhqIP6kBPXalW2dbMTSuB4+8fe+j9juyxwfMwCe9kQPPeiyFn7NMjNfoFOfJ2eXkeQsoUGXg+O2SE3m4Qg2w==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.3.4': - resolution: {integrity: sha512-ay5+qADDN3rwRbRpEhTOreOn1OyJIXS60tg9WMYTWCy3fB6rGoyjLVxc4dR9PYjEdR2iDYsaF5h03NA+XuYPQQ==} + '@next/swc-win32-arm64-msvc@15.5.7': + resolution: {integrity: sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-arm64-msvc@15.4.0-canary.113': - resolution: {integrity: sha512-axV35abh0OJICNaFUaCZtYTrlpJgy2aWTw15PnoY02hps9l4nHP8Ck6fHqOSdzZdshEheNeRxUp3QaHEit2VsQ==} + '@next/swc-win32-arm64-msvc@16.0.7': + resolution: {integrity: sha512-EviG+43iOoBRZg9deGauXExjRphhuYmIOJ12b9sAPy0eQ6iwcPxfED2asb/s2/yiLYOdm37kPaiZu8uXSYPs0Q==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.3.4': - resolution: {integrity: sha512-4kDt31Bc9DGyYs41FTL1/kNpDeHyha2TC0j5sRRoKCyrhNcfZ/nRQkAUlF27mETwm8QyHqIjHJitfcza2Iykfg==} + '@next/swc-win32-x64-msvc@15.5.7': + resolution: {integrity: sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@next/swc-win32-x64-msvc@15.4.0-canary.113': - resolution: {integrity: sha512-0/fPimhZefBograEkK8ONIJw0KoZwIVBuPThFNqZv+8w21qfz6sEonNhko65zx119Vtl6aMnipwzxJp+CiUukg==} + '@next/swc-win32-x64-msvc@16.0.7': + resolution: {integrity: sha512-gniPjy55zp5Eg0896qSrf3yB1dw4F/3s8VK1ephdsZZ129j2n6e1WqCbE2YgcKhW9hPB9TVZENugquWJD5x0ug==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2204,10 +3305,18 @@ packages: resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} engines: {node: ^14.21.3 || >=16} + '@noble/curves@1.9.1': + resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==} + engines: {node: ^14.21.3 || >=16} + '@noble/curves@1.9.2': resolution: {integrity: sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g==} engines: {node: ^14.21.3 || >=16} + '@noble/curves@1.9.7': + resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} + engines: {node: ^14.21.3 || >=16} + '@noble/hashes@1.4.0': resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} @@ -2248,8 +3357,8 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@pkgr/core@0.2.7': - resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} + '@pkgr/core@0.2.9': + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} '@reown/appkit-common@1.7.8': @@ -2281,111 +3390,121 @@ packages: '@reown/appkit@1.7.8': resolution: {integrity: sha512-51kTleozhA618T1UvMghkhKfaPcc9JlKwLJ5uV+riHyvSoWPKPRIa5A6M1Wano5puNyW0s3fwywhyqTHSilkaA==} - '@rollup/rollup-android-arm-eabi@4.44.1': - resolution: {integrity: sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==} + '@rollup/rollup-android-arm-eabi@4.52.5': + resolution: {integrity: sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.44.1': - resolution: {integrity: sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==} + '@rollup/rollup-android-arm64@4.52.5': + resolution: {integrity: sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.44.1': - resolution: {integrity: sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==} + '@rollup/rollup-darwin-arm64@4.52.5': + resolution: {integrity: sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.44.1': - resolution: {integrity: sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==} + '@rollup/rollup-darwin-x64@4.52.5': + resolution: {integrity: sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.44.1': - resolution: {integrity: sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==} + '@rollup/rollup-freebsd-arm64@4.52.5': + resolution: {integrity: sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.44.1': - resolution: {integrity: sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==} + '@rollup/rollup-freebsd-x64@4.52.5': + resolution: {integrity: sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.44.1': - resolution: {integrity: sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==} + '@rollup/rollup-linux-arm-gnueabihf@4.52.5': + resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.44.1': - resolution: {integrity: sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==} + '@rollup/rollup-linux-arm-musleabihf@4.52.5': + resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.44.1': - resolution: {integrity: sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==} + '@rollup/rollup-linux-arm64-gnu@4.52.5': + resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.44.1': - resolution: {integrity: sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==} + '@rollup/rollup-linux-arm64-musl@4.52.5': + resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.44.1': - resolution: {integrity: sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==} + '@rollup/rollup-linux-loong64-gnu@4.52.5': + resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.44.1': - resolution: {integrity: sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==} + '@rollup/rollup-linux-ppc64-gnu@4.52.5': + resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.44.1': - resolution: {integrity: sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==} + '@rollup/rollup-linux-riscv64-gnu@4.52.5': + resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.44.1': - resolution: {integrity: sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==} + '@rollup/rollup-linux-riscv64-musl@4.52.5': + resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.44.1': - resolution: {integrity: sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==} + '@rollup/rollup-linux-s390x-gnu@4.52.5': + resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.44.1': - resolution: {integrity: sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==} + '@rollup/rollup-linux-x64-gnu@4.52.5': + resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.44.1': - resolution: {integrity: sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==} + '@rollup/rollup-linux-x64-musl@4.52.5': + resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.44.1': - resolution: {integrity: sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==} + '@rollup/rollup-openharmony-arm64@4.52.5': + resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.52.5': + resolution: {integrity: sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.44.1': - resolution: {integrity: sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==} + '@rollup/rollup-win32-ia32-msvc@4.52.5': + resolution: {integrity: sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.44.1': - resolution: {integrity: sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==} + '@rollup/rollup-win32-x64-gnu@4.52.5': + resolution: {integrity: sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.52.5': + resolution: {integrity: sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==} cpu: [x64] os: [win32] '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@rushstack/eslint-patch@1.12.0': - resolution: {integrity: sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==} + '@rushstack/eslint-patch@1.14.0': + resolution: {integrity: sha512-WJFej426qe4RWOm9MMtP4V3CV4AucXolQty+GRgAWLgQXmpCuwzs7hEpxxhSc/znXUSxum9d/P/32MW0FlAAlA==} '@safe-global/safe-apps-provider@0.18.6': resolution: {integrity: sha512-4LhMmjPWlIO8TTDC2AwLk44XKXaK6hfBTWyljDm0HQ6TWlOEijVWNrt2s3OCVMSxlXAcEzYfqyu1daHZooTC2Q==} @@ -2429,199 +3548,415 @@ packages: peerDependencies: '@solana/kit': ^5.0 + '@solana-program/compute-budget@0.8.0': + resolution: {integrity: sha512-qPKxdxaEsFxebZ4K5RPuy7VQIm/tfJLa1+Nlt3KNA8EYQkz9Xm8htdoEaXVrer9kpgzzp9R3I3Bh6omwCM06tQ==} + peerDependencies: + '@solana/kit': ^2.1.0 + + '@solana-program/system@0.8.1': + resolution: {integrity: sha512-71U9Mzdpw8HQtfgfJSL5xKZbLMRnza2Llsfk7gGnmg2waqK+o8MMH4YNma8xXS1UmOBptXIiNvoZ3p7cmOVktg==} + peerDependencies: + '@solana/kit': ^3.0 + + '@solana-program/token-2022@0.4.2': + resolution: {integrity: sha512-zIpR5t4s9qEU3hZKupzIBxJ6nUV5/UVyIT400tu9vT1HMs5JHxaTTsb5GUhYjiiTvNwU0MQavbwc4Dl29L0Xvw==} + peerDependencies: + '@solana/kit': ^2.1.0 + '@solana/sysvars': ^2.1.0 + '@solana-program/token-2022@0.6.1': resolution: {integrity: sha512-Ex02cruDMGfBMvZZCrggVR45vdQQSI/unHVpt/7HPt/IwFYB4eTlXtO8otYZyqV/ce5GqZ8S6uwyRf0zy6fdbA==} peerDependencies: '@solana/kit': ^5.0 '@solana/sysvars': ^5.0 + '@solana-program/token@0.5.1': + resolution: {integrity: sha512-bJvynW5q9SFuVOZ5vqGVkmaPGA0MCC+m9jgJj1nk5m20I389/ms69ASnhWGoOPNcie7S9OwBX0gTj2fiyWpfag==} + peerDependencies: + '@solana/kit': ^2.1.0 + + '@solana-program/token@0.6.0': + resolution: {integrity: sha512-omkZh4Tt9rre4wzWHNOhOEHyenXQku3xyc/UrKvShexA/Qlhza67q7uRwmwEDUs4QqoDBidSZPooOmepnA/jig==} + peerDependencies: + '@solana/kit': ^3.0 + '@solana-program/token@0.9.0': resolution: {integrity: sha512-vnZxndd4ED4Fc56sw93cWZ2djEeeOFxtaPS8SPf5+a+JZjKA/EnKqzbE1y04FuMhIVrLERQ8uR8H2h72eZzlsA==} peerDependencies: '@solana/kit': ^5.0 + '@solana/accounts@2.3.0': + resolution: {integrity: sha512-QgQTj404Z6PXNOyzaOpSzjgMOuGwG8vC66jSDB+3zHaRcEPRVRd2sVSrd1U6sHtnV3aiaS6YyDuPQMheg4K2jw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/accounts@3.0.3': + resolution: {integrity: sha512-KqlePrlZaHXfu8YQTCxN204ZuVm9o68CCcUr6l27MG2cuRUtEM1Ta0iR8JFkRUAEfZJC4Cu0ZDjK/v49loXjZQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/accounts@5.0.0': resolution: {integrity: sha512-0JzBdEobgp8NBdhhu+GgwNDh7e8KkHDsSTVZAnNQgvT3taOz0Mwv5E48MuEeDhW6DLFwWVAx/FO3pvibG/NGwA==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/addresses@5.0.0': - resolution: {integrity: sha512-bVk+khc1ZZQHMri25csosM/ikuyPcB/CZidDM/ZMBX0CoJErpHJnmcID5mYOmv4/UHbqo2OANuEaGcFO0Q37sw==} + '@solana/addresses@2.3.0': + resolution: {integrity: sha512-ypTNkY2ZaRFpHLnHAgaW8a83N0/WoqdFvCqf4CQmnMdFsZSdC7qOwcbd7YzdaQn9dy+P2hybewzB+KP7LutxGA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/addresses@3.0.3': + resolution: {integrity: sha512-AuMwKhJI89ANqiuJ/fawcwxNKkSeHH9CApZd2xelQQLS7X8uxAOovpcmEgiObQuiVP944s9ScGUT62Bdul9qYg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/addresses@5.0.0': + resolution: {integrity: sha512-bVk+khc1ZZQHMri25csosM/ikuyPcB/CZidDM/ZMBX0CoJErpHJnmcID5mYOmv4/UHbqo2OANuEaGcFO0Q37sw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/assertions@2.3.0': + resolution: {integrity: sha512-Ekoet3khNg3XFLN7MIz8W31wPQISpKUGDGTylLptI+JjCDWx3PIa88xjEMqFo02WJ8sBj2NLV64Xg1sBcsHjZQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/assertions@3.0.3': + resolution: {integrity: sha512-2qspxdbWp2y62dfCIlqeWQr4g+hE8FYSSwcaP6itwMwGRb8393yDGCJfI/znuzJh6m/XVWhMHIgFgsBwnevCmg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/assertions@5.0.0': + resolution: {integrity: sha512-2kIykk90kYciQW6bp+KaE6jRd1Y2CgHPeJxxlc5chQnjhoG6eiD8VXvocs6AvqPTht0p/SoEj9jH5tT4oG/bcg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/buffer-layout@4.0.1': + resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} + engines: {node: '>=5.10'} + + '@solana/codecs-core@2.3.0': + resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-core@3.0.3': + resolution: {integrity: sha512-emKykJ3h1DmnDOY29Uv9eJXP8E/FHzvlUBJ6te+5EbKdFjj7vdlKYPfDxOI6iGdXTY+YC/ELtbNBh6QwF2uEDQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-core@5.0.0': + resolution: {integrity: sha512-rCG2d8OaamVF2/J//YyCgDqNJpUytVVltw9C8mJtEz5c6Se/LR6BFuG8g4xeJswq/ab4RFk5/HFdgbvNjKgQjA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-data-structures@2.3.0': + resolution: {integrity: sha512-qvU5LE5DqEdYMYgELRHv+HMOx73sSoV1ZZkwIrclwUmwTbTaH8QAJURBj0RhQ/zCne7VuLLOZFFGv6jGigWhSw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-data-structures@3.0.3': + resolution: {integrity: sha512-R15cLp8riJvToXziW8lP6AMSwsztGhEnwgyGmll32Mo0Yjq+hduW2/fJrA/TJs6tA/OgTzMQjlxgk009EqZHCw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-data-structures@5.0.0': + resolution: {integrity: sha512-y503Pqmv0LHcfcf0vQJGaxDvydQJbyCo8nK3nxn56EhFj5lBQ1NWb3WvTd83epigwuZurW2MhJARrpikfhQglQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-numbers@2.3.0': + resolution: {integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-numbers@3.0.3': + resolution: {integrity: sha512-pfXkH9J0glrM8qj6389GAn30+cJOxzXLR2FsPOHCUMXrqLhGjMMZAWhsQkpOQ37SGc/7EiQsT/gmyGC7gxHqJQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-numbers@5.0.0': + resolution: {integrity: sha512-a2+skRLuUK02f/XFe4L0e1+wHCyfK25PkyseFps1v1l4pvevukFwth/EhSyrs6w5CsTJRVoR7MuE3E00PM4egw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-strings@2.3.0': + resolution: {integrity: sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==} + engines: {node: '>=20.18.0'} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: '>=5.3.3' + + '@solana/codecs-strings@3.0.3': + resolution: {integrity: sha512-VHBXnnTVtcQ1j+7Vrz+qSYo38no+jiHRdGnhFspRXEHNJbllzwKqgBE7YN3qoIXH+MKxgJUcwO5KHmdzf8Wn2A==} + engines: {node: '>=20.18.0'} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: '>=5.3.3' + + '@solana/codecs-strings@5.0.0': + resolution: {integrity: sha512-ALkRwpV8bGR6qjAYw0YXZwp2YI4wzvKOJGmx04Ut8gMdbaUx7qOcJkhEQKI6ZVC3lAWSIS1N1wGccUZDwvfKxw==} + engines: {node: '>=20.18.0'} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: '>=5.3.3' + + '@solana/codecs@2.3.0': + resolution: {integrity: sha512-JVqGPkzoeyU262hJGdH64kNLH0M+Oew2CIPOa/9tR3++q2pEd4jU2Rxdfye9sd0Ce3XJrR5AIa8ZfbyQXzjh+g==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs@3.0.3': + resolution: {integrity: sha512-GOHwTlIQsCoJx9Ryr6cEf0FHKAQ7pY4aO4xgncAftrv0lveTQ1rPP2inQ1QT0gJllsIa8nwbfXAADs9nNJxQDA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs@5.0.0': + resolution: {integrity: sha512-KOw0gFUSBxIMDWLJ3AkVFkEci91dw0Rpx3C6y83Our7fSW+SEP8vRZklCElieYR85LHVB1QIEhoeHR7rc+Ifkw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/errors@2.3.0': + resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: '>=5.3.3' + + '@solana/errors@3.0.3': + resolution: {integrity: sha512-1l84xJlHNva6io62PcYfUamwWlc0eM95nHgCrKX0g0cLoC6D6QHYPCEbEVkR+C5UtP9JDgyQM8MFiv+Ei5tO9Q==} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: '>=5.3.3' + + '@solana/errors@5.0.0': + resolution: {integrity: sha512-gTuhzO6E+ydfAAzqmqdPcvFyJwAzFKKIrqtnZPpgAuomcPYu+HSo0tuwSM/cTX0djmHt+GoOsf/julph+nvs2w==} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: '>=5.3.3' + + '@solana/fast-stable-stringify@2.3.0': + resolution: {integrity: sha512-KfJPrMEieUg6D3hfQACoPy0ukrAV8Kio883llt/8chPEG3FVTX9z/Zuf4O01a15xZmBbmQ7toil2Dp0sxMJSxw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/fast-stable-stringify@3.0.3': + resolution: {integrity: sha512-ED0pxB6lSEYvg+vOd5hcuQrgzEDnOrURFgp1ZOY+lQhJkQU6xo+P829NcJZQVP1rdU2/YQPAKJKEseyfe9VMIw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/fast-stable-stringify@5.0.0': + resolution: {integrity: sha512-sGTbu7a4/olL+8EIOOJ7IZjzqOOpCJcK1UaVJ6015sRgo9vwGf4jg9KtXEYv5LVhLCTYmAb50L4BaIUcBph/Ig==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/functional@2.3.0': + resolution: {integrity: sha512-AgsPh3W3tE+nK3eEw/W9qiSfTGwLYEvl0rWaxHht/lRcuDVwfKRzeSa5G79eioWFFqr+pTtoCr3D3OLkwKz02Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/functional@3.0.3': + resolution: {integrity: sha512-2qX1kKANn8995vOOh5S9AmF4ItGZcfbny0w28Eqy8AFh+GMnSDN4gqpmV2LvxBI9HibXZptGH3RVOMk82h1Mpw==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/assertions@5.0.0': - resolution: {integrity: sha512-2kIykk90kYciQW6bp+KaE6jRd1Y2CgHPeJxxlc5chQnjhoG6eiD8VXvocs6AvqPTht0p/SoEj9jH5tT4oG/bcg==} + '@solana/functional@5.0.0': + resolution: {integrity: sha512-UNBrpfzBL4dKD2iucjNnrkFbnjz5ZYDu2OvrIBAcCSQsxxgHMamUj1n3EDe6kl1us49YG1r05Ho8QLqNrbkVbw==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/buffer-layout-utils@0.2.0': - resolution: {integrity: sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==} - engines: {node: '>= 10'} - - '@solana/buffer-layout@4.0.1': - resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} - engines: {node: '>=5.10'} + '@solana/instruction-plans@3.0.3': + resolution: {integrity: sha512-eqoaPtWtmLTTpdvbt4BZF5H6FIlJtXi9H7qLOM1dLYonkOX2Ncezx5NDCZ9tMb2qxVMF4IocYsQnNSnMfjQF1w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' - '@solana/codecs-core@2.0.0-rc.1': - resolution: {integrity: sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==} + '@solana/instruction-plans@5.0.0': + resolution: {integrity: sha512-n9oFOMFUPYKEhsXzrXT97QBQ2WvOTar+5SFEj/IOtRuCn4gl2kh0369cjXZpFwUdE3tmKr1zfYFNwbtiNx5pvg==} + engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5' + typescript: '>=5.3.3' - '@solana/codecs-core@2.1.1': - resolution: {integrity: sha512-iPQW3UZ2Vi7QFBo2r9tw0NubtH8EdrhhmZulx6lC8V5a+qjaxovtM/q/UW2BTNpqqHLfO0tIcLyBLrNH4HTWPg==} + '@solana/instructions@2.3.0': + resolution: {integrity: sha512-PLMsmaIKu7hEAzyElrk2T7JJx4D+9eRwebhFZpy2PXziNSmFF929eRHKUsKqBFM3cYR1Yy3m6roBZfA+bGE/oQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/codecs-core@5.0.0': - resolution: {integrity: sha512-rCG2d8OaamVF2/J//YyCgDqNJpUytVVltw9C8mJtEz5c6Se/LR6BFuG8g4xeJswq/ab4RFk5/HFdgbvNjKgQjA==} + '@solana/instructions@3.0.3': + resolution: {integrity: sha512-4csIi8YUDb5j/J+gDzmYtOvq7ZWLbCxj4t0xKn+fPrBk/FD2pK29KVT3Fu7j4Lh1/ojunQUP9X4NHwUexY3PnA==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/codecs-data-structures@2.0.0-rc.1': - resolution: {integrity: sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog==} + '@solana/instructions@5.0.0': + resolution: {integrity: sha512-12dbrmwERT1o6NTr/Uvrjj/ZsiteSXoT5Gi+dnjIeRNHWg9H+gEFuFzJvTDVKlNg34CZ71xdvbVdbV0V8gKGvg==} + engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5' + typescript: '>=5.3.3' - '@solana/codecs-data-structures@5.0.0': - resolution: {integrity: sha512-y503Pqmv0LHcfcf0vQJGaxDvydQJbyCo8nK3nxn56EhFj5lBQ1NWb3WvTd83epigwuZurW2MhJARrpikfhQglQ==} + '@solana/keys@2.3.0': + resolution: {integrity: sha512-ZVVdga79pNH+2pVcm6fr2sWz9HTwfopDVhYb0Lh3dh+WBmJjwkabXEIHey2rUES7NjFa/G7sV8lrUn/v8LDCCQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/codecs-numbers@2.0.0-rc.1': - resolution: {integrity: sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==} + '@solana/keys@3.0.3': + resolution: {integrity: sha512-tp8oK9tMadtSIc4vF4aXXWkPd4oU5XPW8nf28NgrGDWGt25fUHIydKjkf2hPtMt9i1WfRyQZ33B5P3dnsNqcPQ==} + engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5' + typescript: '>=5.3.3' - '@solana/codecs-numbers@2.1.1': - resolution: {integrity: sha512-m20IUPJhPUmPkHSlZ2iMAjJ7PaYUvlMtFhCQYzm9BEBSI6OCvXTG3GAPpAnSGRBfg5y+QNqqmKn4QHU3B6zzCQ==} + '@solana/keys@5.0.0': + resolution: {integrity: sha512-kWkR7NslpTttk5i1BhBNCDtVQDkEtgkdsM3Jp9TGPk0GFjBjBwrQStw3vvwLe8itEIvRFGFZU6JHEk8HLS0WLQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/codecs-numbers@5.0.0': - resolution: {integrity: sha512-a2+skRLuUK02f/XFe4L0e1+wHCyfK25PkyseFps1v1l4pvevukFwth/EhSyrs6w5CsTJRVoR7MuE3E00PM4egw==} + '@solana/kit@2.3.0': + resolution: {integrity: sha512-sb6PgwoW2LjE5oTFu4lhlS/cGt/NB3YrShEyx7JgWFWysfgLdJnhwWThgwy/4HjNsmtMrQGWVls0yVBHcMvlMQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/codecs-strings@2.0.0-rc.1': - resolution: {integrity: sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g==} + '@solana/kit@3.0.3': + resolution: {integrity: sha512-CEEhCDmkvztd1zbgADsEQhmj9GyWOOGeW1hZD+gtwbBSF5YN1uofS/pex5MIh/VIqKRj+A2UnYWI1V+9+q/lyQ==} + engines: {node: '>=20.18.0'} peerDependencies: - fastestsmallesttextencoderdecoder: ^1.0.22 - typescript: '>=5' + typescript: '>=5.3.3' - '@solana/codecs-strings@5.0.0': - resolution: {integrity: sha512-ALkRwpV8bGR6qjAYw0YXZwp2YI4wzvKOJGmx04Ut8gMdbaUx7qOcJkhEQKI6ZVC3lAWSIS1N1wGccUZDwvfKxw==} + '@solana/kit@5.0.0': + resolution: {integrity: sha512-3ahtzmmMgU+1l2YMhQJSKKm14IdvCycOE/m4XNMu/4icBIptmBgZxrmgRpPHqBilBa+Krp/hBuTg4HWl9IAgWw==} engines: {node: '>=20.18.0'} peerDependencies: - fastestsmallesttextencoderdecoder: ^1.0.22 typescript: '>=5.3.3' - '@solana/codecs@2.0.0-rc.1': - resolution: {integrity: sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ==} + '@solana/nominal-types@2.3.0': + resolution: {integrity: sha512-uKlMnlP4PWW5UTXlhKM8lcgIaNj8dvd8xO4Y9l+FVvh9RvW2TO0GwUO6JCo7JBzCB0PSqRJdWWaQ8pu1Ti/OkA==} + engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5' + typescript: '>=5.3.3' - '@solana/codecs@5.0.0': - resolution: {integrity: sha512-KOw0gFUSBxIMDWLJ3AkVFkEci91dw0Rpx3C6y83Our7fSW+SEP8vRZklCElieYR85LHVB1QIEhoeHR7rc+Ifkw==} + '@solana/nominal-types@3.0.3': + resolution: {integrity: sha512-aZavCiexeUAoMHRQg4s1AHkH3wscbOb70diyfjhwZVgFz1uUsFez7csPp9tNFkNolnadVb2gky7yBk3IImQJ6A==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/errors@2.0.0-rc.1': - resolution: {integrity: sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==} - hasBin: true + '@solana/nominal-types@5.0.0': + resolution: {integrity: sha512-Qn7xH4UG2rDAv+wAyheP4jWvX3oQmbZ/woxFZwug7PaRLvyjUswGr38Hil+SjiQyFDo+un1UqWM9N9yusUeeZQ==} + engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5' + typescript: '>=5.3.3' - '@solana/errors@2.1.1': - resolution: {integrity: sha512-sj6DaWNbSJFvLzT8UZoabMefQUfSW/8tXK7NTiagsDmh+Q87eyQDDC9L3z+mNmx9b6dEf6z660MOIplDD2nfEw==} + '@solana/options@2.3.0': + resolution: {integrity: sha512-PPnnZBRCWWoZQ11exPxf//DRzN2C6AoFsDI/u2AsQfYih434/7Kp4XLpfOMT/XESi+gdBMFNNfbES5zg3wAIkw==} engines: {node: '>=20.18.0'} - hasBin: true peerDependencies: typescript: '>=5.3.3' - '@solana/errors@5.0.0': - resolution: {integrity: sha512-gTuhzO6E+ydfAAzqmqdPcvFyJwAzFKKIrqtnZPpgAuomcPYu+HSo0tuwSM/cTX0djmHt+GoOsf/julph+nvs2w==} + '@solana/options@3.0.3': + resolution: {integrity: sha512-jarsmnQ63RN0JPC5j9sgUat07NrL9PC71XU7pUItd6LOHtu4+wJMio3l5mT0DHVfkfbFLL6iI6+QmXSVhTNF3g==} engines: {node: '>=20.18.0'} - hasBin: true peerDependencies: typescript: '>=5.3.3' - '@solana/fast-stable-stringify@5.0.0': - resolution: {integrity: sha512-sGTbu7a4/olL+8EIOOJ7IZjzqOOpCJcK1UaVJ6015sRgo9vwGf4jg9KtXEYv5LVhLCTYmAb50L4BaIUcBph/Ig==} + '@solana/options@5.0.0': + resolution: {integrity: sha512-ezHVBFb9FXVSn8LUVRD2tLb6fejU0x8KtGEYyCYh0J0pQuXSITV0IQCjcEopvu/ZxWdXOJyzjvmymnhz90on5A==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/functional@5.0.0': - resolution: {integrity: sha512-UNBrpfzBL4dKD2iucjNnrkFbnjz5ZYDu2OvrIBAcCSQsxxgHMamUj1n3EDe6kl1us49YG1r05Ho8QLqNrbkVbw==} + '@solana/programs@2.3.0': + resolution: {integrity: sha512-UXKujV71VCI5uPs+cFdwxybtHZAIZyQkqDiDnmK+DawtOO9mBn4Nimdb/6RjR2CXT78mzO9ZCZ3qfyX+ydcB7w==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/instruction-plans@5.0.0': - resolution: {integrity: sha512-n9oFOMFUPYKEhsXzrXT97QBQ2WvOTar+5SFEj/IOtRuCn4gl2kh0369cjXZpFwUdE3tmKr1zfYFNwbtiNx5pvg==} + '@solana/programs@3.0.3': + resolution: {integrity: sha512-JZlVE3/AeSNDuH3aEzCZoDu8GTXkMpGXxf93zXLzbxfxhiQ/kHrReN4XE/JWZ/uGWbaFZGR5B3UtdN2QsoZL7w==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/instructions@5.0.0': - resolution: {integrity: sha512-12dbrmwERT1o6NTr/Uvrjj/ZsiteSXoT5Gi+dnjIeRNHWg9H+gEFuFzJvTDVKlNg34CZ71xdvbVdbV0V8gKGvg==} + '@solana/programs@5.0.0': + resolution: {integrity: sha512-BKOfBDrSUCJGZ+qKk2aFLu0nU9/84o6z/VDCJkLjaNNuTv8nOlSYq5flNzo1eyJmnpyW372qNvqqRN3AS23+FQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/keys@5.0.0': - resolution: {integrity: sha512-kWkR7NslpTttk5i1BhBNCDtVQDkEtgkdsM3Jp9TGPk0GFjBjBwrQStw3vvwLe8itEIvRFGFZU6JHEk8HLS0WLQ==} + '@solana/promises@2.3.0': + resolution: {integrity: sha512-GjVgutZKXVuojd9rWy1PuLnfcRfqsaCm7InCiZc8bqmJpoghlyluweNc7ml9Y5yQn1P2IOyzh9+p/77vIyNybQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/kit@5.0.0': - resolution: {integrity: sha512-3ahtzmmMgU+1l2YMhQJSKKm14IdvCycOE/m4XNMu/4icBIptmBgZxrmgRpPHqBilBa+Krp/hBuTg4HWl9IAgWw==} + '@solana/promises@3.0.3': + resolution: {integrity: sha512-K+UflGBVxj30XQMHTylHHZJdKH5QG3oj5k2s42GrZ/Wbu72oapVJySMBgpK45+p90t8/LEqV6rRPyTXlet9J+Q==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/nominal-types@5.0.0': - resolution: {integrity: sha512-Qn7xH4UG2rDAv+wAyheP4jWvX3oQmbZ/woxFZwug7PaRLvyjUswGr38Hil+SjiQyFDo+un1UqWM9N9yusUeeZQ==} + '@solana/promises@5.0.0': + resolution: {integrity: sha512-Qmg3UfYfWINEUvBQL3DkPOq34tTg5cfrkPlDtJmi8RVifsPqb6hksbKZGu7ASLZohxIDGmnYQY6oELI7Me+5yw==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/options@2.0.0-rc.1': - resolution: {integrity: sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA==} + '@solana/rpc-api@2.3.0': + resolution: {integrity: sha512-UUdiRfWoyYhJL9PPvFeJr4aJ554ob2jXcpn4vKmRVn9ire0sCbpQKYx6K8eEKHZWXKrDW8IDspgTl0gT/aJWVg==} + engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5' + typescript: '>=5.3.3' - '@solana/options@5.0.0': - resolution: {integrity: sha512-ezHVBFb9FXVSn8LUVRD2tLb6fejU0x8KtGEYyCYh0J0pQuXSITV0IQCjcEopvu/ZxWdXOJyzjvmymnhz90on5A==} + '@solana/rpc-api@3.0.3': + resolution: {integrity: sha512-Yym9/Ama62OY69rAZgbOCAy1QlqaWAyb0VlqFuwSaZV1pkFCCFSwWEJEsiN1n8pb2ZP+RtwNvmYixvWizx9yvA==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/programs@5.0.0': - resolution: {integrity: sha512-BKOfBDrSUCJGZ+qKk2aFLu0nU9/84o6z/VDCJkLjaNNuTv8nOlSYq5flNzo1eyJmnpyW372qNvqqRN3AS23+FQ==} + '@solana/rpc-api@5.0.0': + resolution: {integrity: sha512-IJbZZnX2B1ldXPok1NhneXTYq9ZvdJbE5Pryr03pZTlPJaWGqDcZuQ14nwR4s6PoUUgdT+p87QlLZqLb8MusoQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/promises@5.0.0': - resolution: {integrity: sha512-Qmg3UfYfWINEUvBQL3DkPOq34tTg5cfrkPlDtJmi8RVifsPqb6hksbKZGu7ASLZohxIDGmnYQY6oELI7Me+5yw==} + '@solana/rpc-parsed-types@2.3.0': + resolution: {integrity: sha512-B5pHzyEIbBJf9KHej+zdr5ZNAdSvu7WLU2lOUPh81KHdHQs6dEb310LGxcpCc7HVE8IEdO20AbckewDiAN6OCg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-api@5.0.0': - resolution: {integrity: sha512-IJbZZnX2B1ldXPok1NhneXTYq9ZvdJbE5Pryr03pZTlPJaWGqDcZuQ14nwR4s6PoUUgdT+p87QlLZqLb8MusoQ==} + '@solana/rpc-parsed-types@3.0.3': + resolution: {integrity: sha512-/koM05IM2fU91kYDQxXil3VBNlOfcP+gXE0js1sdGz8KonGuLsF61CiKB5xt6u1KEXhRyDdXYLjf63JarL4Ozg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' @@ -2632,24 +3967,74 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-spec-types@2.3.0': + resolution: {integrity: sha512-xQsb65lahjr8Wc9dMtP7xa0ZmDS8dOE2ncYjlvfyw/h4mpdXTUdrSMi6RtFwX33/rGuztQ7Hwaid5xLNSLvsFQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/rpc-spec-types@3.0.3': + resolution: {integrity: sha512-A6Jt8SRRetnN3CeGAvGJxigA9zYRslGgWcSjueAZGvPX+MesFxEUjSWZCfl+FogVFvwkqfkgQZQbPAGZQFJQ6Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-spec-types@5.0.0': resolution: {integrity: sha512-B0P/ylXVaCG5oSIV+kB88s2qoW996D8iKhc7RyF0C/AyYvklF6kCwv0N9ZVrWp0ibjlQ8St290WbBHJyo7QZkA==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-spec@2.3.0': + resolution: {integrity: sha512-fA2LMX4BMixCrNB2n6T83AvjZ3oUQTu7qyPLyt8gHQaoEAXs8k6GZmu6iYcr+FboQCjUmRPgMaABbcr9j2J9Sw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/rpc-spec@3.0.3': + resolution: {integrity: sha512-MZn5/8BebB6MQ4Gstw6zyfWsFAZYAyLzMK+AUf/rSfT8tPmWiJ/mcxnxqOXvFup/l6D67U8pyGpIoFqwCeZqqA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-spec@5.0.0': resolution: {integrity: sha512-1LD2SYEQ5bYhiBumznAPzymtxSX4nYLZd6u+FA0bAxNBVzHDvUUQzVSXHAoWROhlGrCyvtALTs9u0DIDlgZHCA==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-subscriptions-api@2.3.0': + resolution: {integrity: sha512-9mCjVbum2Hg9KGX3LKsrI5Xs0KX390lS+Z8qB80bxhar6MJPugqIPH8uRgLhCW9GN3JprAfjRNl7our8CPvsPQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/rpc-subscriptions-api@3.0.3': + resolution: {integrity: sha512-MGgVK3PUS15qsjuhimpzGZrKD/CTTvS0mAlQ0Jw84zsr1RJVdQJK/F0igu07BVd172eTZL8d90NoAQ3dahW5pA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-subscriptions-api@5.0.0': resolution: {integrity: sha512-DGUn3C12swV2FConOlLFN14npIrCtnxehtMLjszMC7g6p/P6WNIz5uAgF7YcIkLBDV8uTeWhM0azmK+V8Qqhvg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-subscriptions-channel-websocket@2.3.0': + resolution: {integrity: sha512-2oL6ceFwejIgeWzbNiUHI2tZZnaOxNTSerszcin7wYQwijxtpVgUHiuItM/Y70DQmH9sKhmikQp+dqeGalaJxw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + ws: ^8.18.0 + + '@solana/rpc-subscriptions-channel-websocket@3.0.3': + resolution: {integrity: sha512-zUzUlb8Cwnw+SHlsLrSqyBRtOJKGc+FvSNJo/vWAkLShoV0wUDMPv7VvhTngJx3B/3ANfrOZ4i08i9QfYPAvpQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + ws: ^8.18.0 + '@solana/rpc-subscriptions-channel-websocket@5.0.0': resolution: {integrity: sha512-vsYXyjVX/kExfpr91zfMKTmWKKFCM+dkhXQDAz5aEE7kAF3KSZDiOGeYvN8Rc85lbIt9QK6BLAT+NBMv4/N9Qg==} engines: {node: '>=20.18.0'} @@ -2657,65 +4042,143 @@ packages: typescript: '>=5.3.3' ws: ^8.18.0 + '@solana/rpc-subscriptions-spec@2.3.0': + resolution: {integrity: sha512-rdmVcl4PvNKQeA2l8DorIeALCgJEMSu7U8AXJS1PICeb2lQuMeaR+6cs/iowjvIB0lMVjYN2sFf6Q3dJPu6wWg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/rpc-subscriptions-spec@3.0.3': + resolution: {integrity: sha512-9KpQ32OBJWS85mn6q3gkM0AjQe1LKYlMU7gpJRrla/lvXxNLhI95tz5K6StctpUreVmRWTVkNamHE69uUQyY8A==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-subscriptions-spec@5.0.0': resolution: {integrity: sha512-erRLvZMncwnciJP6I1SlAk0CyRGIgt83PyHWOVCRXENP9Q5dZbZ9pm4lar2yIp8EjIMnodGHsQWIlKc1hlCQlQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-subscriptions@2.3.0': + resolution: {integrity: sha512-Uyr10nZKGVzvCOqwCZgwYrzuoDyUdwtgQRefh13pXIrdo4wYjVmoLykH49Omt6abwStB0a4UL5gX9V4mFdDJZg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/rpc-subscriptions@3.0.3': + resolution: {integrity: sha512-LRvz6NaqvtsYFd32KwZ+rwYQ9XCs+DWjV8BvBLsJpt9/NWSuHf/7Sy/vvP6qtKxut692H/TMvHnC4iulg0WmiQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-subscriptions@5.0.0': resolution: {integrity: sha512-cziOSzom/bwFZXViR9J+MxDsdLMcfvrXGw5Icng7dYODFKuVqfsDrQoG8uekJc4fREnbPEM2U+u9YnYSYbFbww==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-transformers@2.3.0': + resolution: {integrity: sha512-UuHYK3XEpo9nMXdjyGKkPCOr7WsZsxs7zLYDO1A5ELH3P3JoehvrDegYRAGzBS2VKsfApZ86ZpJToP0K3PhmMA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/rpc-transformers@3.0.3': + resolution: {integrity: sha512-lzdaZM/dG3s19Tsk4mkJA5JBoS1eX9DnD7z62gkDwrwJDkDBzkAJT9aLcsYFfTmwTfIp6uU2UPgGYc97i1wezw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-transformers@5.0.0': resolution: {integrity: sha512-EMHhSgfF6/T4FfHbLaBP08SIj1ZAjxJr6WPNZMHLV7Cup8UfiB9TNV+bPQkum7JbVQNhUKzkKEEmyYqPfQoV9w==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-transport-http@2.3.0': + resolution: {integrity: sha512-HFKydmxGw8nAF5N+S0NLnPBDCe5oMDtI2RAmW8DMqP4U3Zxt2XWhvV1SNkAldT5tF0U1vP+is6fHxyhk4xqEvg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/rpc-transport-http@3.0.3': + resolution: {integrity: sha512-bIXFwr2LR5A97Z46dI661MJPbHnPfcShBjFzOS/8Rnr8P4ho3j/9EUtjDrsqoxGJT3SLWj5OlyXAlaDAvVTOUQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-transport-http@5.0.0': resolution: {integrity: sha512-RoIEvWp7yc7rIRzNkOyjLs2UQF0odIEMWj87dbD4Ir4hwTCGo/TSTfQF/8KDV2etdke3Fa1K+W1NkpG2POqWFg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-types@2.3.0': + resolution: {integrity: sha512-O09YX2hED2QUyGxrMOxQ9GzH1LlEwwZWu69QbL4oYmIf6P5dzEEHcqRY6L1LsDVqc/dzAdEs/E1FaPrcIaIIPw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/rpc-types@3.0.3': + resolution: {integrity: sha512-petWQ5xSny9UfmC3Qp2owyhNU0w9SyBww4+v7tSVyXMcCC9v6j/XsqTeimH1S0qQUllnv0/FY83ohFaxofmZ6Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-types@5.0.0': resolution: {integrity: sha512-JMbhwnV6nX4ezJv/KmaElOR0r/MZTKzKpaz6cv7FopLNuPrYCBrRCZKuM2XQh6gUbt9Mey08/KBOmOGmzTbL/g==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc@2.3.0': + resolution: {integrity: sha512-ZWN76iNQAOCpYC7yKfb3UNLIMZf603JckLKOOLTHuy9MZnTN8XV6uwvDFhf42XvhglgUjGCEnbUqWtxQ9pa/pQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/rpc@3.0.3': + resolution: {integrity: sha512-3oukAaLK78GegkKcm6iNmRnO4mFeNz+BMvA8T56oizoBNKiRVEq/6DFzVX/LkmZ+wvD601pAB3uCdrTPcC0YKQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc@5.0.0': resolution: {integrity: sha512-Myx/ZBmMHkgh9Di3tLzc+vd30f+6YC1JXr9+YmIHKEeqN/+iTHkDJU2E/hGRLy8vTOBOU7+2466A+dLnSVuGkg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/signers@5.0.0': - resolution: {integrity: sha512-9Hw6HekSEzj5O7UBBFPrxk96W5e8tMI3n7KbW7/QiKBDpuvYw9WtnjOsWUE7LqQoc1P0JjGEsrmxE9raQBLvuQ==} + '@solana/signers@2.3.0': + resolution: {integrity: sha512-OSv6fGr/MFRx6J+ZChQMRqKNPGGmdjkqarKkRzkwmv7v8quWsIRnJT5EV8tBy3LI4DLO/A8vKiNSPzvm1TdaiQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/spl-token-group@0.0.7': - resolution: {integrity: sha512-V1N/iX7Cr7H0uazWUT2uk27TMqlqedpXHRqqAbVO2gvmJyT0E0ummMEAVQeXZ05ZhQ/xF39DLSdBp90XebWEug==} - engines: {node: '>=16'} + '@solana/signers@3.0.3': + resolution: {integrity: sha512-UwCd/uPYTZiwd283JKVyOWLLN5sIgMBqGDyUmNU3vo9hcmXKv5ZGm/9TvwMY2z35sXWuIOcj7etxJ8OoWc/ObQ==} + engines: {node: '>=20.18.0'} peerDependencies: - '@solana/web3.js': ^1.95.3 + typescript: '>=5.3.3' - '@solana/spl-token-metadata@0.1.6': - resolution: {integrity: sha512-7sMt1rsm/zQOQcUWllQX9mD2O6KhSAtY1hFR2hfFwgqfFWzSY9E9GDvFVNYUI1F0iQKcm6HmePU9QbKRXTEBiA==} - engines: {node: '>=16'} + '@solana/signers@5.0.0': + resolution: {integrity: sha512-9Hw6HekSEzj5O7UBBFPrxk96W5e8tMI3n7KbW7/QiKBDpuvYw9WtnjOsWUE7LqQoc1P0JjGEsrmxE9raQBLvuQ==} + engines: {node: '>=20.18.0'} peerDependencies: - '@solana/web3.js': ^1.95.3 + typescript: '>=5.3.3' - '@solana/spl-token@0.4.13': - resolution: {integrity: sha512-cite/pYWQZZVvLbg5lsodSovbetK/eA24gaR0eeUeMuBAMNrT8XFCwaygKy0N2WSg3gSyjjNpIeAGBAKZaY/1w==} - engines: {node: '>=16'} + '@solana/subscribable@2.3.0': + resolution: {integrity: sha512-DkgohEDbMkdTWiKAoatY02Njr56WXx9e/dKKfmne8/Ad6/2llUIrax78nCdlvZW9quXMaXPTxZvdQqo9N669Og==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/subscribable@3.0.3': + resolution: {integrity: sha512-FJ27LKGHLQ5GGttPvTOLQDLrrOZEgvaJhB7yYaHAhPk25+p+erBaQpjePhfkMyUbL1FQbxn1SUJmS6jUuaPjlQ==} + engines: {node: '>=20.18.0'} peerDependencies: - '@solana/web3.js': ^1.95.5 + typescript: '>=5.3.3' '@solana/subscribable@5.0.0': resolution: {integrity: sha512-C2TydIRRd5XUJ8asbARi67Sj/3DRLubWalnNoafBhDsrb88jsRVylntvwXgBw/+lwJdEPEsUnxvcdgdm+3lFlw==} @@ -2723,24 +4186,72 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/sysvars@2.3.0': + resolution: {integrity: sha512-LvjADZrpZ+CnhlHqfI5cmsRzX9Rpyb1Ox2dMHnbsRNzeKAMhu9w4ZBIaeTdO322zsTr509G1B+k2ABD3whvUBA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/sysvars@3.0.3': + resolution: {integrity: sha512-GnHew+QeKCs2f9ow+20swEJMH4mDfJA/QhtPgOPTYQx/z69J4IieYJ7fZenSHnA//lJ45fVdNdmy1trypvPLBQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/sysvars@5.0.0': resolution: {integrity: sha512-F/GEb2rS8mrgDd79lDPyu8za9jGE6cRlS4jHNeKCkvOCJxdKQbX34JIzx4kwzjtvk7O8/yrDHfGdpA8nBg/l4w==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/transaction-confirmation@2.3.0': + resolution: {integrity: sha512-UiEuiHCfAAZEKdfne/XljFNJbsKAe701UQHKXEInYzIgBjRbvaeYZlBmkkqtxwcasgBTOmEaEKT44J14N9VZDw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/transaction-confirmation@3.0.3': + resolution: {integrity: sha512-dXx0OLtR95LMuARgi2dDQlL1QYmk56DOou5q9wKymmeV3JTvfDExeWXnOgjRBBq/dEfj4ugN1aZuTaS18UirFw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/transaction-confirmation@5.0.0': resolution: {integrity: sha512-LpusTopYIuQC8hBCloExkTr4Z5/zdp5f4IIbzD5XFeW3xXPZytS3H1IDMGk4bmLdZi9zQNA4lnNHKra5IncRbw==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/transaction-messages@2.3.0': + resolution: {integrity: sha512-bgqvWuy3MqKS5JdNLH649q+ngiyOu5rGS3DizSnWwYUd76RxZl1kN6CoqHSrrMzFMvis6sck/yPGG3wqrMlAww==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/transaction-messages@3.0.3': + resolution: {integrity: sha512-s+6NWRnBhnnjFWV4x2tzBzoWa6e5LiIxIvJlWwVQBFkc8fMGY04w7jkFh0PM08t/QFKeXBEWkyBDa/TFYdkWug==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/transaction-messages@5.0.0': resolution: {integrity: sha512-rJLe1wUGW5DovQFV0gjXHXnriPxTBgZ3TvGWnjCu2OIBU8mcQkQVJ7zzVZY2IAYlmJ6OSF9nvzhSt/ncPbkJPg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/transactions@2.3.0': + resolution: {integrity: sha512-LnTvdi8QnrQtuEZor5Msje61sDpPstTVwKg4y81tNxDhiyomjuvnSNLAq6QsB9gIxUqbNzPZgOG9IU4I4/Uaug==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/transactions@3.0.3': + resolution: {integrity: sha512-iMX+n9j4ON7H1nKlWEbMqMOpKYC6yVGxKKmWHT1KdLRG7v+03I4DnDeFoI+Zmw56FA+7Bbne8jwwX60Q1vk/MQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/transactions@5.0.0': resolution: {integrity: sha512-4TcsqH7JtgRKGGBIRRGz0n+tXu4h5TPPC49kkV0ygIndQaHW7FOZUYTwQ0epq0A5h9KYi+ClNbzF9xiuDbAD5Q==} engines: {node: '>=20.18.0'} @@ -2751,8 +4262,8 @@ packages: resolution: {integrity: sha512-ZhpZtD+4VArf6RPitsVExvgkF+nGghd1rzPjd97GmBximpnt1rsUxMOEyoIEuH3XBxPyNB6Us7ha7RHWQR+abg==} engines: {node: '>=16'} - '@solana/web3.js@1.98.2': - resolution: {integrity: sha512-BqVwEG+TaG2yCkBMbD3C4hdpustR4FpuUFRPUmqRZYYlPI9Hg4XMWxHWOWRzHE9Lkc9NDjzXFX7lDXSgzC7R1A==} + '@solana/web3.js@1.98.4': + resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==} '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} @@ -2832,20 +4343,17 @@ packages: resolution: {integrity: sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==} engines: {node: '>=14'} - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} - '@tanstack/query-core@5.81.5': - resolution: {integrity: sha512-ZJOgCy/z2qpZXWaj/oxvodDx07XcQa9BF92c0oINjHkoqUPsmm3uG08HpTaviviZ/N9eP1f9CM7mKSEkIo7O1Q==} + '@tanstack/query-core@5.90.8': + resolution: {integrity: sha512-4E0RP/0GJCxSNiRF2kAqE/LQkTJVlL/QNU7gIJSptaseV9HP6kOuA+N11y4bZKZxa3QopK3ZuewwutHx6DqDXQ==} - '@tanstack/react-query@5.81.5': - resolution: {integrity: sha512-lOf2KqRRiYWpQT86eeeftAGnjuTR35myTP8MXyvHa81VlomoAWNEd8x5vkcAfQefu0qtYCvyqLropFZqgI2EQw==} + '@tanstack/react-query@5.90.8': + resolution: {integrity: sha512-/3b9QGzkf4rE5/miL6tyhldQRlLXzMHcySOm/2Tm2OLEFE9P1ImkH0+OviDBSvyAvtAOJocar5xhd7vxdLi3aQ==} peerDependencies: react: ^18 || ^19 @@ -2853,26 +4361,14 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - - '@tybys/wasm-util@0.9.0': - resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} '@types/body-parser@1.19.6': resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} - '@types/chai@5.2.2': - resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} @@ -2889,8 +4385,8 @@ packages: '@types/express-serve-static-core@4.19.6': resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} - '@types/express-serve-static-core@5.0.6': - resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==} + '@types/express-serve-static-core@5.1.0': + resolution: {integrity: sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==} '@types/express@4.17.23': resolution: {integrity: sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==} @@ -2907,6 +4403,9 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/lodash@4.17.20': + resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} + '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} @@ -2922,19 +4421,22 @@ packages: '@types/node@22.16.0': resolution: {integrity: sha512-B2egV9wALML1JCpv3VQoQ+yesQKAmNMBIAY7OteVrikcOcAkWm+dGL6qpeCktPjAv6N1JLnhbNiqS35UpFyBsQ==} + '@types/prompts@2.4.9': + resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==} + '@types/qs@6.14.0': resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/react-dom@19.1.6': - resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} + '@types/react-dom@19.2.2': + resolution: {integrity: sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==} peerDependencies: - '@types/react': ^19.0.0 + '@types/react': ^19.2.0 - '@types/react@19.1.8': - resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} + '@types/react@19.2.2': + resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==} '@types/send@0.17.5': resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==} @@ -2954,157 +4456,216 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - '@typescript-eslint/eslint-plugin@8.35.1': - resolution: {integrity: sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg==} + '@typescript-eslint/eslint-plugin@8.46.2': + resolution: {integrity: sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.35.1 + '@typescript-eslint/parser': ^8.46.2 eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.35.1': - resolution: {integrity: sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w==} + '@typescript-eslint/eslint-plugin@8.48.0': + resolution: {integrity: sha512-XxXP5tL1txl13YFtrECECQYeZjBZad4fyd3cFV4a19LkAY/bIp9fev3US4S5fDVV2JaYFiKAZ/GRTOLer+mbyQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: + '@typescript-eslint/parser': ^8.48.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.35.1': - resolution: {integrity: sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q==} + '@typescript-eslint/parser@8.46.2': + resolution: {integrity: sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <5.9.0' + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.48.0': + resolution: {integrity: sha512-jCzKdm/QK0Kg4V4IK/oMlRZlY+QOcdjv89U2NgKHZk1CYTj82/RVSx1mV/0gqCVMJ/DA+Zf/S4NBWNF8GQ+eqQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.46.2': + resolution: {integrity: sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.48.0': + resolution: {integrity: sha512-Ne4CTZyRh1BecBf84siv42wv5vQvVmgtk8AuiEffKTUo3DrBaGYZueJSxxBZ8fjk/N3DrgChH4TOdIOwOwiqqw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.46.2': + resolution: {integrity: sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/scope-manager@8.48.0': + resolution: {integrity: sha512-uGSSsbrtJrLduti0Q1Q9+BF1/iFKaxGoQwjWOIVNJv0o6omrdyR8ct37m4xIl5Zzpkp69Kkmvom7QFTtue89YQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.46.2': + resolution: {integrity: sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.35.1': - resolution: {integrity: sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg==} + '@typescript-eslint/tsconfig-utils@8.48.0': + resolution: {integrity: sha512-WNebjBdFdyu10sR1M4OXTt2OkMd5KWIL+LLfeH9KhgP+jzfDV/LI3eXzwJ1s9+Yc0Kzo2fQCdY/OpdusCMmh6w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/tsconfig-utils@8.35.1': - resolution: {integrity: sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ==} + '@typescript-eslint/type-utils@8.46.2': + resolution: {integrity: sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <5.9.0' + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.35.1': - resolution: {integrity: sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ==} + '@typescript-eslint/type-utils@8.48.0': + resolution: {integrity: sha512-zbeVaVqeXhhab6QNEKfK96Xyc7UQuoFWERhEnj3mLVnUWrQnv15cJNseUni7f3g557gm0e46LZ6IJ4NJVOgOpw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.46.2': + resolution: {integrity: sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/types@8.48.0': + resolution: {integrity: sha512-cQMcGQQH7kwKoVswD1xdOytxQR60MWKM1di26xSUtxehaDs/32Zpqsu5WJlXTtTTqyAVK8R7hvsUnIXRS+bjvA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.35.1': - resolution: {integrity: sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ==} + '@typescript-eslint/typescript-estree@8.46.2': + resolution: {integrity: sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/typescript-estree@8.48.0': + resolution: {integrity: sha512-ljHab1CSO4rGrQIAyizUS6UGHHCiAYhbfcIZ1zVJr5nMryxlXMVWS3duFPSKvSUbFPwkXMFk1k0EMIjub4sRRQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/typescript-estree@8.35.1': - resolution: {integrity: sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g==} + '@typescript-eslint/utils@8.46.2': + resolution: {integrity: sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <5.9.0' + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.35.1': - resolution: {integrity: sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ==} + '@typescript-eslint/utils@8.48.0': + resolution: {integrity: sha512-yTJO1XuGxCsSfIVt1+1UrLHtue8xz16V8apzPYI06W0HbEbEWHxHXgZaAgavIkoh+GeV6hKKd5jm0sS6OYxWXQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.46.2': + resolution: {integrity: sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.35.1': - resolution: {integrity: sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw==} + '@typescript-eslint/visitor-keys@8.48.0': + resolution: {integrity: sha512-T0XJMaRPOH3+LBbAfzR2jalckP1MSG/L9eUtY0DEzUyVaXJ/t6zN0nR7co5kz0Jko/nkSYCBRkz1djvjajVTTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@unrs/resolver-binding-android-arm-eabi@1.10.1': - resolution: {integrity: sha512-zohDKXT1Ok0yhbVGff4YAg9HUs5ietG5GpvJBPFSApZnGe7uf2cd26DRhKZbn0Be6xHUZrSzP+RAgMmzyc71EA==} + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} cpu: [arm] os: [android] - '@unrs/resolver-binding-android-arm64@1.10.1': - resolution: {integrity: sha512-tAN6k5UrTd4nicpA7s2PbjR/jagpDzAmvXFjbpTazUe5FRsFxVcBlS1F5Lzp5jtWU6bdiqRhSvd4X8rdpCffeA==} + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} cpu: [arm64] os: [android] - '@unrs/resolver-binding-darwin-arm64@1.10.1': - resolution: {integrity: sha512-+FCsag8WkauI4dQ50XumCXdfvDCZEpMUnvZDsKMxfOisnEklpDFXc6ThY0WqybBYZbiwR5tWcFaZmI0G6b4vrg==} + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} cpu: [arm64] os: [darwin] - '@unrs/resolver-binding-darwin-x64@1.10.1': - resolution: {integrity: sha512-qYKGGm5wk71ONcXTMZ0+J11qQeOAPz3nw6VtqrBUUELRyXFyvK8cHhHsLBFR4GHnilc2pgY1HTB2TvdW9wO26Q==} + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} cpu: [x64] os: [darwin] - '@unrs/resolver-binding-freebsd-x64@1.10.1': - resolution: {integrity: sha512-hOHMAhbvIQ63gkpgeNsXcWPSyvXH7ZEyeg254hY0Lp/hX8NdW+FsUWq73g9946Pc/BrcVI/I3C1cmZ4RCX9bNw==} + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} cpu: [x64] os: [freebsd] - '@unrs/resolver-binding-linux-arm-gnueabihf@1.10.1': - resolution: {integrity: sha512-6ds7+zzHJgTDmpe0gmFcOTvSUhG5oZukkt+cCsSb3k4Uiz2yEQB4iCRITX2hBwSW+p8gAieAfecITjgqCkswXw==} + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm-musleabihf@1.10.1': - resolution: {integrity: sha512-P7A0G2/jW00diNJyFeq4W9/nxovD62Ay8CMP4UK9OymC7qO7rG1a8Upad68/bdfpIOn7KSp7Aj/6lEW3yyznAA==} + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm64-gnu@1.10.1': - resolution: {integrity: sha512-Cg6xzdkrpltcTPO4At+A79zkC7gPDQIgosJmVV8M104ImB6KZi1MrNXgDYIAfkhUYjPzjNooEDFRAwwPadS7ZA==} + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} cpu: [arm64] os: [linux] - '@unrs/resolver-binding-linux-arm64-musl@1.10.1': - resolution: {integrity: sha512-aNeg99bVkXa4lt+oZbjNRPC8ZpjJTKxijg/wILrJdzNyAymO2UC/HUK1UfDjt6T7U5p/mK24T3CYOi3/+YEQSA==} + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} cpu: [arm64] os: [linux] - '@unrs/resolver-binding-linux-ppc64-gnu@1.10.1': - resolution: {integrity: sha512-ylz5ojeXrkPrtnzVhpCO+YegG63/aKhkoTlY8PfMfBfLaUG8v6m6iqrL7sBUKdVBgOB4kSTUPt9efQdA/Y3Z/w==} + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} cpu: [ppc64] os: [linux] - '@unrs/resolver-binding-linux-riscv64-gnu@1.10.1': - resolution: {integrity: sha512-xcWyhmJfXXOxK7lvE4+rLwBq+on83svlc0AIypfe6x4sMJR+S4oD7n9OynaQShfj2SufPw2KJAotnsNb+4nN2g==} + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} cpu: [riscv64] os: [linux] - '@unrs/resolver-binding-linux-riscv64-musl@1.10.1': - resolution: {integrity: sha512-mW9JZAdOCyorgi1eLJr4gX7xS67WNG9XNPYj5P8VuttK72XNsmdw9yhOO4tDANMgiLXFiSFaiL1gEpoNtRPw/A==} + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} cpu: [riscv64] os: [linux] - '@unrs/resolver-binding-linux-s390x-gnu@1.10.1': - resolution: {integrity: sha512-NZGKhBy6xkJ0k09cWNZz4DnhBcGlhDd3W+j7EYoNvf5TSwj2K6kbmfqTWITEgkvjsMUjm1wsrc4IJaH6VtjyHQ==} + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} cpu: [s390x] os: [linux] - '@unrs/resolver-binding-linux-x64-gnu@1.10.1': - resolution: {integrity: sha512-VsjgckJ0gNMw7p0d8In6uPYr+s0p16yrT2rvG4v2jUpEMYkpnfnCiALa9SWshbvlGjKQ98Q2x19agm3iFk8w8Q==} + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} cpu: [x64] os: [linux] - '@unrs/resolver-binding-linux-x64-musl@1.10.1': - resolution: {integrity: sha512-idMnajMeejnaFi0Mx9UTLSYFDAOTfAEP7VjXNgxKApso3Eu2Njs0p2V95nNIyFi4oQVGFmIuCkoznAXtF/Zbmw==} + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} cpu: [x64] os: [linux] - '@unrs/resolver-binding-wasm32-wasi@1.10.1': - resolution: {integrity: sha512-7jyhjIRNFjzlr8x5pth6Oi9hv3a7ubcVYm2GBFinkBQKcFhw4nIs5BtauSNtDW1dPIGrxF0ciynCZqzxMrYMsg==} + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@unrs/resolver-binding-win32-arm64-msvc@1.10.1': - resolution: {integrity: sha512-TY79+N+Gkoo7E99K+zmsKNeiuNJYlclZJtKqsHSls8We2iGhgxtletVsiBYie93MSTDRDMI8pkBZJlIJSZPrdA==} + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} cpu: [arm64] os: [win32] - '@unrs/resolver-binding-win32-ia32-msvc@1.10.1': - resolution: {integrity: sha512-BAJN5PEPlEV+1m8+PCtFoKm3LQ1P57B4Z+0+efU0NzmCaGk7pUaOxuPgl+m3eufVeeNBKiPDltG0sSB9qEfCxw==} + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} cpu: [ia32] os: [win32] - '@unrs/resolver-binding-win32-x64-msvc@1.10.1': - resolution: {integrity: sha512-2v3erKKmmCyIVvvhI2nF15qEbdBpISTq44m9pyd5gfIJB1PN94oePTLWEd82XUbIbvKhv76xTSeUQSCOGesLeg==} + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} cpu: [x64] os: [win32] @@ -3137,18 +4698,28 @@ packages: '@vitest/utils@3.2.4': resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} - '@wagmi/connectors@5.8.5': - resolution: {integrity: sha512-CHh4uYP6MziCMlSVXmuAv7wMoYWdxXliuzwCRAxHNNkgXE7z37ez5XzJu0Sm39NUau3Fl8WSjwKo4a4w9BOYNA==} + '@wagmi/connectors@5.11.2': + resolution: {integrity: sha512-OkiElOI8xXGPDZE5UdG6NgDT3laSkEh9llX1DDapUnfnKecK3Tr/HUf5YzgwDhEoox8mdxp+8ZCjtnTKz56SdA==} + peerDependencies: + '@wagmi/core': 2.21.2 + typescript: '>=5.0.4' + viem: 2.x + peerDependenciesMeta: + typescript: + optional: true + + '@wagmi/connectors@6.1.0': + resolution: {integrity: sha512-MnpJHEABUIsajNxLc6br0LiqJvoFZbavQ6yG+mQb7Xlb3Hmm3IRjH5NU1g2zw5PCTRd3BFQLjwniLdwDnUPYNw==} peerDependencies: - '@wagmi/core': 2.17.3 + '@wagmi/core': 2.22.1 typescript: '>=5.0.4' viem: 2.x peerDependenciesMeta: typescript: optional: true - '@wagmi/core@2.17.3': - resolution: {integrity: sha512-fgZR9fAiCFtGaosTspkTx5lidccq9Z5xRWOk1HG0VfB6euQGw2//Db7upiP4uQ7DPst2YS9yQN2A1m9+iJLYCw==} + '@wagmi/core@2.22.1': + resolution: {integrity: sha512-cG/xwQWsBEcKgRTkQVhH29cbpbs/TdcUJVFXCyri3ZknxhMyGv0YEjTcrNpRgt2SaswL1KrvslSNYKKo+5YEAg==} peerDependencies: '@tanstack/query-core': '>=5.0.0' typescript: '>=5.0.4' @@ -3281,6 +4852,28 @@ packages: zod: optional: true + abitype@1.1.0: + resolution: {integrity: sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3.22.0 || ^4.0.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + + abitype@1.1.1: + resolution: {integrity: sha512-Loe5/6tAgsBukY95eGaPSDmQHIjRZYQq8PB1MpsNccDIK8WiV+Uw6WzaIXipvaxTEL2yEB0OpEaQv3gs8pkS9Q==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3.22.0 || ^4.0.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -3290,17 +4883,13 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} hasBin: true - agent-base@7.1.3: - resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} agentkeepalive@4.6.0: @@ -3310,20 +4899,23 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} any-promise@1.3.0: @@ -3337,9 +4929,6 @@ packages: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} - arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -3417,8 +5006,8 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axe-core@4.10.3: - resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} + axe-core@4.11.0: + resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==} engines: {node: '>=4'} axios-retry@4.5.0: @@ -3429,6 +5018,9 @@ packages: axios@1.10.0: resolution: {integrity: sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==} + axios@1.12.2: + resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -3460,23 +5052,17 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + baseline-browser-mapping@2.8.19: + resolution: {integrity: sha512-zoKGUdu6vb2jd3YOq0nnhEDQVbPcHhco3UImJrv5dSkvxTc2pl2WjOPsjZXDwPDSl5eghIMuY3R6J9NDKF3KcQ==} + hasBin: true + big.js@6.2.2: resolution: {integrity: sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==} - bigint-buffer@1.1.5: - resolution: {integrity: sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==} - engines: {node: '>= 10.0.0'} - - bignumber.js@9.3.0: - resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - bn.js@4.12.2: resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==} @@ -3493,8 +5079,8 @@ packages: borsh@0.7.0: resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} - bowser@2.11.0: - resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + bowser@2.12.1: + resolution: {integrity: sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==} brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -3522,12 +5108,12 @@ packages: resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} engines: {node: '>= 0.10'} - browserify-sign@4.2.3: - resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==} - engines: {node: '>= 0.12'} + browserify-sign@4.2.5: + resolution: {integrity: sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==} + engines: {node: '>= 0.10'} - browserslist@4.25.1: - resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==} + browserslist@4.27.0: + resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -3559,10 +5145,6 @@ packages: peerDependencies: esbuild: '>=0.18' - busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -3599,21 +5181,17 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001726: - resolution: {integrity: sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==} + caniuse-lite@1.0.30001751: + resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} - chai@5.2.0: - resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} - engines: {node: '>=12'} + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.4.1: - resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} - 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} @@ -3633,8 +5211,8 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} - cipher-base@1.0.6: - resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} + cipher-base@1.0.7: + resolution: {integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==} engines: {node: '>= 0.10'} client-only@0.0.1: @@ -3658,13 +5236,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - - color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -3672,13 +5243,9 @@ packages: comlink@4.4.2: resolution: {integrity: sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==} - commander@12.1.0: - resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} - engines: {node: '>=18'} - - commander@13.1.0: - resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} - engines: {node: '>=18'} + commander@14.0.0: + resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} + engines: {node: '>=20'} commander@14.0.1: resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==} @@ -3730,8 +5297,8 @@ packages: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} - core-js-compat@3.43.0: - resolution: {integrity: sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==} + core-js-compat@3.46.0: + resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -3753,18 +5320,12 @@ packages: create-ecdh@4.0.4: resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} - create-hash@1.1.3: - resolution: {integrity: sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==} - create-hash@1.2.0: resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} create-hmac@1.1.7: resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - cross-fetch@3.2.0: resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} @@ -3858,8 +5419,8 @@ packages: supports-color: optional: true - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -3867,8 +5428,8 @@ packages: supports-color: optional: true - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -3880,8 +5441,8 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} - decimal.js@10.5.0: - resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} decode-uri-component@0.2.2: resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} @@ -3939,17 +5500,13 @@ packages: detect-browser@5.3.0: resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} - detect-libc@2.0.4: - resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - diffie-hellman@5.0.3: resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} @@ -4001,15 +5558,15 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - eciesjs@0.4.15: - resolution: {integrity: sha512-r6kEJXDKecVOCj2nLMuXK/FCPeurW33+3JRpfXVbjLja3XUYFfD9I/JBreH6sUyzcm3G/YQboBjMla6poKeSdA==} + eciesjs@0.4.16: + resolution: {integrity: sha512-dS5cbA9rA2VR4Ybuvhg6jvdmp46ubLn3E+px8cG/35aEDNclrqoCjg6mt0HYZ/M+OoESS3jSkCrqk1kWAEhWAw==} engines: {bun: '>=1', deno: '>=2', node: '>=16'} ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.179: - resolution: {integrity: sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==} + electron-to-chromium@1.5.239: + resolution: {integrity: sha512-1y5w0Zsq39MSPmEjHjbizvhYoTaulVtivpxkp5q5kaPmQtsK6/2nvAzGRxNMS9DoYySp9PkW0MAQDwU1m764mg==} elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} @@ -4049,8 +5606,8 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} es-abstract@1.24.0: resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} @@ -4117,8 +5674,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-config-next@15.1.7: - resolution: {integrity: sha512-zXoMnYUIy3XHaAoOhrcYkT9UQWvXqWju2K7NNsmb5wd/7XESDwof61eUdW4QhERr3eJ9Ko/vnXqIrj8kk/drYw==} + eslint-config-next@15.1.9: + resolution: {integrity: sha512-Yx0rjzk+o1SdKkzV0R/f/R3gvdpFA8FTtEKdFvESmiQ40uPnbRD52sOlZcTCkP5QLImnjVIit9qo8DYhrTSsIQ==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 typescript: '>=3.3.1' @@ -4126,6 +5683,15 @@ packages: typescript: optional: true + eslint-config-next@16.0.7: + resolution: {integrity: sha512-WubFGLFHfk2KivkdRGfx6cGSFhaQqhERRfyO8BRx+qiGPGp7WLKcPvYC4mdx1z3VhVRcrfFzczjjTrbJZOpnEQ==} + peerDependencies: + eslint: '>=9.0.0' + typescript: '>=3.3.1' + peerDependenciesMeta: + typescript: + optional: true + eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} @@ -4185,8 +5751,8 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-prettier@5.5.1: - resolution: {integrity: sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==} + eslint-plugin-prettier@5.5.4: + resolution: {integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -4205,6 +5771,12 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + eslint-plugin-react-hooks@7.0.1: + resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + eslint-plugin-react@7.37.5: resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} engines: {node: '>=4'} @@ -4223,8 +5795,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.30.1: - resolution: {integrity: sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==} + eslint@9.38.0: + resolution: {integrity: sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -4294,8 +5866,8 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} - expect-type@1.2.1: - resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} + expect-type@1.2.2: + resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} engines: {node: '>=12.0.0'} express@4.21.2: @@ -4340,14 +5912,18 @@ packages: fast-stable-stringify@1.0.0: resolution: {integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fastestsmallesttextencoderdecoder@1.0.22: resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - fdir@6.4.6: - resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -4358,9 +5934,6 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} - file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -4412,6 +5985,10 @@ packages: resolution: {integrity: sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==} engines: {node: '>= 6'} + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} + engines: {node: '>= 6'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -4435,6 +6012,10 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -4478,6 +6059,10 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -4505,8 +6090,8 @@ packages: resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - h3@1.15.3: - resolution: {integrity: sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ==} + h3@1.15.4: + resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==} has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} @@ -4531,13 +6116,14 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hash-base@2.0.2: - resolution: {integrity: sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==} - hash-base@3.0.5: resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} engines: {node: '>= 0.10'} + hash-base@3.1.2: + resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} + engines: {node: '>= 0.8'} + hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} @@ -4545,11 +6131,17 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - hono@4.8.3: - resolution: {integrity: sha512-jYZ6ZtfWjzBdh8H/0CIFfCBHaFL75k+KMzaM177hrWWm2TWL39YMYaJgB74uK/niRc866NMlH9B8uCvIo284WQ==} + hono@4.10.2: + resolution: {integrity: sha512-p6fyzl+mQo6uhESLxbF5WlBOAJMDh36PljwlKtP5V1v09NxlqGru3ShK+4wKhSuhuYf8qxMmrivHOa/M7q0sMg==} engines: {node: '>=16.9.0'} html-encoding-sniffer@4.0.0: @@ -4583,6 +6175,9 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + idb-keyval@6.2.1: + resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} + idb-keyval@6.2.2: resolution: {integrity: sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==} @@ -4630,9 +6225,6 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - is-async-function@2.1.1: resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} engines: {node: '>= 0.4'} @@ -4683,8 +6275,8 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-function@1.1.0: - resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} engines: {node: '>= 0.4'} is-glob@4.0.3: @@ -4797,8 +6389,8 @@ packages: jose@5.10.0: resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} - jose@6.0.11: - resolution: {integrity: sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==} + jose@6.1.0: + resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==} joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} @@ -4827,11 +6419,6 @@ packages: canvas: optional: true - jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -4853,6 +6440,9 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -4882,6 +6472,10 @@ packages: keyvaluestorage-interface@1.0.0: resolution: {integrity: sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + language-subtag-registry@0.3.23: resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} @@ -4900,11 +6494,11 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lit-element@4.2.0: - resolution: {integrity: sha512-MGrXJVAI5x+Bfth/pU9Kst1iWID6GHDLEzFEnyULB/sFiRLgkd8NPK/PeeXxktA3T6EIIaq8U3KcbTU5XFcP2Q==} + lit-element@4.2.1: + resolution: {integrity: sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==} - lit-html@3.3.0: - resolution: {integrity: sha512-RHoswrFAxY2d8Cf2mm4OZ1DgzCoBKUKSPvA1fhtSELxUERq2aQQ2h05pO9j81gS1o7RIRJ+CePLogfyahwmynw==} + lit-html@3.3.1: + resolution: {integrity: sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==} lit@3.3.0: resolution: {integrity: sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==} @@ -4937,8 +6531,8 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - loupe@3.1.4: - resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -4949,11 +6543,8 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - magic-string@0.30.17: - resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + magic-string@0.30.19: + resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} @@ -5045,12 +6636,15 @@ packages: typescript: optional: true - mlly@1.7.4: - resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + mlly@1.8.0: + resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -5065,8 +6659,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - napi-postinstall@0.3.0: - resolution: {integrity: sha512-M7NqKyhODKV1gRLdkwE7pDsZP2/SC2a2vHkOYh9MCpKMbWVfyVfUw5MaH83Fv6XMjxr5jryUp3IDDL9rlxsTeA==} + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} hasBin: true @@ -5077,13 +6671,13 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} - next@15.3.4: - resolution: {integrity: sha512-mHKd50C+mCjam/gcnwqL1T1vPx/XQNFlXqFIVdgQdVAFY9iIQtY0IfaVflEYzKiqjeA7B0cYYMaCrmAYFjs4rA==} + next@15.5.7: + resolution: {integrity: sha512-+t2/0jIJ48kUpGKkdlhgkv+zPTEOoXyr60qXe68eB/pl3CMJaLeIGjzp5D6Oqt25hCBiBTt8wEeeAzfJvUKnPQ==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 + '@playwright/test': ^1.51.1 babel-plugin-react-compiler: '*' react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 @@ -5098,9 +6692,9 @@ packages: sass: optional: true - next@15.4.0-canary.113: - resolution: {integrity: sha512-OfYlHgR8UOAu9m3zS74fM9yPCRHuRE8q2en7votw84FLm7AWP2FtepznMj+t+65cd4IUdyXefkJvGsHcDmXC2Q==} - engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} + next@16.0.7: + resolution: {integrity: sha512-3mBRJyPxT4LOxAJI6IsXeFtKfiJUbjCLgvXO02fV8Wy/lIhPvP94Fe7dGhUgHXcQy4sSuYwQNcOLhIfOm0rL0A==} + engines: {node: '>=20.9.0'} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -5125,8 +6719,8 @@ packages: node-addon-api@2.0.2: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} - node-fetch-native@1.6.6: - resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} @@ -5141,11 +6735,11 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - node-mock-http@1.0.1: - resolution: {integrity: sha512-0gJJgENizp4ghds/Ywu2FCmcRsgBTmRQzYPZm61wy+Em2sBarSka0OhQS5huLBg6od1zkNpnWMCZloQDFVvOMQ==} + node-mock-http@1.0.3: + resolution: {integrity: sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==} - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + node-releases@2.0.26: + resolution: {integrity: sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==} normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} @@ -5158,8 +6752,8 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nwsapi@2.2.20: - resolution: {integrity: sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==} + nwsapi@2.2.22: + resolution: {integrity: sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==} obj-multiplex@1.0.0: resolution: {integrity: sha512-0GNJAOsHoBHeNTvl5Vt6IWnpUEcc3uSRxzBri7EDyIcMgYvnY2JL2qdeV5zTMjWQX5OHcD5amcW2HFfDh0gjIA==} @@ -5217,6 +6811,12 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + openapi-fetch@0.13.8: + resolution: {integrity: sha512-yJ4QKRyNxE44baQ9mY5+r/kAzZ8yXMemtNAOFwOzRXJscdjSxxzWSNlyBAr+o5JjkUw9Lc3W7OIoca0cY3PYnQ==} + + openapi-typescript-helpers@0.0.15: + resolution: {integrity: sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -5241,6 +6841,14 @@ packages: typescript: optional: true + ox@0.6.9: + resolution: {integrity: sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + ox@0.8.1: resolution: {integrity: sha512-e+z5epnzV+Zuz91YYujecW8cF01mzmrUtWotJ0oEPym/G82uccs7q0WDHTYL3eiONbTUEvcZrptAKLgTBD3u2A==} peerDependencies: @@ -5249,6 +6857,22 @@ packages: typescript: optional: true + ox@0.9.12: + resolution: {integrity: sha512-esyA5WXfFhlxpgzoVIEreRaasqqv95sjFpk3L4Me4RWk8bgBDe+J4wO3RZ5ikYmJ2Bbjyv+jKgxyaOzX6JpHPA==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + ox@0.9.6: + resolution: {integrity: sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -5276,8 +6900,8 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parse-asn1@5.1.7: - resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==} + parse-asn1@5.1.9: + resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==} engines: {node: '>= 0.10'} parse-imports-exports@0.2.4: @@ -5326,9 +6950,9 @@ packages: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} - pbkdf2@3.1.3: - resolution: {integrity: sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==} - engines: {node: '>=0.12'} + pbkdf2@3.1.5: + resolution: {integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==} + engines: {node: '>= 0.10'} picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -5337,8 +6961,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} pify@2.3.0: @@ -5378,6 +7002,26 @@ packages: resolution: {integrity: sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==} engines: {node: '>=12.0.0'} + porto@0.2.19: + resolution: {integrity: sha512-q1vEJgdtlEOf6byWgD31GHiMwpfLuxFSfx9f7Sw4RGdvpQs2ANBGfnzzardADZegr87ZXsebSp+3vaaznEUzPQ==} + hasBin: true + peerDependencies: + '@tanstack/react-query': '>=5.59.0' + '@wagmi/core': '>=2.16.3' + react: '>=18' + typescript: '>=5.4.0' + viem: '>=2.37.0' + wagmi: '>=2.0.0' + peerDependenciesMeta: + '@tanstack/react-query': + optional: true + react: + optional: true + typescript: + optional: true + wagmi: + optional: true + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -5388,8 +7032,8 @@ packages: peerDependencies: postcss: ^8.0.0 - postcss-js@4.0.1: - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + postcss-js@4.1.0: + resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 @@ -5445,8 +7089,11 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} - preact@10.26.9: - resolution: {integrity: sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA==} + preact@10.24.2: + resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} + + preact@10.27.2: + resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -5467,6 +7114,10 @@ packages: process-warning@1.0.0: resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==} + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -5531,6 +7182,11 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + react-dom@19.2.0: + resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} + peerDependencies: + react: ^19.2.0 + react-dom@19.2.1: resolution: {integrity: sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==} peerDependencies: @@ -5539,6 +7195,10 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react@19.2.0: + resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} + engines: {node: '>=0.10.0'} + react@19.2.1: resolution: {integrity: sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==} engines: {node: '>=0.10.0'} @@ -5569,8 +7229,8 @@ packages: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} - regenerate-unicode-properties@10.2.0: - resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} + regenerate-unicode-properties@10.2.2: + resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} engines: {node: '>=4'} regenerate@1.4.2: @@ -5580,21 +7240,25 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} - regexpu-core@6.2.0: - resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} + regexpu-core@6.4.0: + resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} engines: {node: '>=4'} regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - regjsparser@0.12.0: - resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} + regjsparser@0.13.0: + resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} hasBin: true require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} @@ -5609,8 +7273,8 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} hasBin: true @@ -5622,19 +7286,17 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - ripemd160@2.0.1: - resolution: {integrity: sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==} - - ripemd160@2.0.2: - resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + ripemd160@2.0.3: + resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} + engines: {node: '>= 0.8'} - rollup@4.44.1: - resolution: {integrity: sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==} + rollup@4.52.5: + resolution: {integrity: sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - rpc-websockets@9.1.1: - resolution: {integrity: sha512-1IXGM/TfPT6nfYMIXkJdzn+L4JEsmb0FL1O2OBjaH03V3yuUDdKFulGLMFG6ErV+8pZ5HVC0limve01RyO+saA==} + rpc-websockets@9.2.0: + resolution: {integrity: sha512-DS/XHdPxplQTtNRKiBCRWGBJfjOk56W7fyFUpiYi9fSTWTzoEMbUkn3J4gB0IMniIEVeAGR1/rzFQogzD5MxvQ==} rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -5678,8 +7340,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true @@ -5714,8 +7376,8 @@ packages: engines: {node: '>= 0.10'} hasBin: true - sharp@0.34.2: - resolution: {integrity: sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==} + sharp@0.34.4: + resolution: {integrity: sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: @@ -5752,8 +7414,8 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -5780,6 +7442,7 @@ packages: source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions spdx-exceptions@2.5.0: resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} @@ -5787,8 +7450,8 @@ packages: spdx-expression-parse@4.0.0: resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} - spdx-license-ids@3.0.21: - resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} + spdx-license-ids@3.0.22: + resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} split-on-first@1.1.0: resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} @@ -5808,8 +7471,8 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - std-env@3.9.0: - resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} @@ -5827,10 +7490,6 @@ packages: stream-shift@1.0.3: resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} - streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - strict-uri-encode@2.0.0: resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} engines: {node: '>=4'} @@ -5876,8 +7535,8 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} strip-bom@3.0.0: @@ -5892,8 +7551,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@3.0.0: - resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} styled-jsx@5.1.6: resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} @@ -5940,15 +7599,15 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - synckit@0.11.8: - resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} + synckit@0.11.11: + resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} engines: {node: ^14.18.0 || >=16.0.0} tailwind-merge@2.6.0: resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==} - tailwindcss@3.4.17: - resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} + tailwindcss@3.4.18: + resolution: {integrity: sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==} engines: {node: '>=14.0.0'} hasBin: true @@ -5971,8 +7630,8 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyglobby@0.2.14: - resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} tinypool@1.1.1: @@ -5983,8 +7642,8 @@ packages: resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - tinyspy@4.0.3: - resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} tldts-core@6.1.86: @@ -5994,8 +7653,8 @@ packages: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true - to-buffer@1.2.1: - resolution: {integrity: sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==} + to-buffer@1.2.2: + resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} engines: {node: '>= 0.4'} to-regex-range@5.0.1: @@ -6033,20 +7692,6 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - tsconfck@3.1.6: resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} engines: {node: ^18 || >=20} @@ -6131,6 +7776,13 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} + typescript-eslint@8.48.0: + resolution: {integrity: sha512-fcKOvQD9GUn3Xw63EgiDqhvWJ5jsyZUaekl3KVpGsDJnN46WJTe3jWxtQP9lMZm1LJNkFLlTaWAxK2vUQR+cqw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + typescript@5.8.3: resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} engines: {node: '>=14.17'} @@ -6163,23 +7815,23 @@ packages: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} - unicode-match-property-value-ecmascript@2.2.0: - resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} engines: {node: '>=4'} - unicode-property-aliases-ecmascript@2.1.0: - resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} engines: {node: '>=4'} unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unrs-resolver@1.10.1: - resolution: {integrity: sha512-EFrL7Hw4kmhZdwWO3dwwFJo6hO3FXuQ6Bg8BK/faHZ9m1YxqBS31BNSTxklIQkxK/4LlV8zTYnPsIRLBzTzjCA==} + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} - unstorage@1.16.0: - resolution: {integrity: sha512-WQ37/H5A7LcRPWfYOrDa1Ys02xAbpPJq6q5GkO88FBXVSQzHd7+BjEwfRqyaSWCv9MbsJy058GWjjPjcJ16GGA==} + unstorage@1.17.1: + resolution: {integrity: sha512-KKGwRTT0iVBCErKemkJCLs7JdxNVfqTPc/85ae1XES0+bsHbc/sFBfVi5kJp156cc51BHinIH2l3k0EZ24vOBQ==} peerDependencies: '@azure/app-configuration': ^1.8.0 '@azure/cosmos': ^4.2.0 @@ -6189,10 +7841,11 @@ packages: '@azure/storage-blob': ^12.26.0 '@capacitor/preferences': ^6.0.3 || ^7.0.0 '@deno/kv': '>=0.9.0' - '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 '@planetscale/database': ^1.19.0 '@upstash/redis': ^1.34.3 '@vercel/blob': '>=0.27.1' + '@vercel/functions': ^2.2.12 || ^3.0.0 '@vercel/kv': ^1.0.1 aws4fetch: ^1.0.20 db0: '>=0.2.1' @@ -6224,6 +7877,8 @@ packages: optional: true '@vercel/blob': optional: true + '@vercel/functions': + optional: true '@vercel/kv': optional: true aws4fetch: @@ -6237,8 +7892,8 @@ packages: uploadthing: optional: true - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -6278,9 +7933,6 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true - v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - valtio@1.13.2: resolution: {integrity: sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A==} engines: {node: '>=12.20.0'} @@ -6313,6 +7965,22 @@ packages: typescript: optional: true + viem@2.38.3: + resolution: {integrity: sha512-By2TutLv07iNHHtWqHHzjGipevYsfGqT7KQbGEmqLco1qTJxKnvBbSviqiu6/v/9REV6Q/FpmIxf2Z7/l5AbcQ==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + + viem@2.40.3: + resolution: {integrity: sha512-feYfEpbgjRkZYQpwcgxqkWzjxHI5LSDAjcGetHHwDRuX9BRQHUdV8ohrCosCYpdEhus/RknD3/bOd4qLYVPPuA==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + vite-node@3.2.4: resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -6326,8 +7994,8 @@ packages: vite: optional: true - vite@6.3.5: - resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} + vite@6.4.1: + resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -6398,8 +8066,8 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} - wagmi@2.15.6: - resolution: {integrity: sha512-tR4tm+7eE0UloQe1oi4hUIjIDyjv5ImQlzq/QcvvfJYWF/EquTfGrmht6+nTYGCIeSzeEvbK90KgWyNqa+HD7Q==} + wagmi@2.18.2: + resolution: {integrity: sha512-9jFip+0ZfjMBxT72m02MZD2+VmQQ/UmqZhHl+98N9HEqXLn765fIu45QPV85DAnQqIHD81gvY3vTvfWt16A5yQ==} peerDependencies: '@tanstack/react-query': '>=5.0.0' react: '>=18' @@ -6548,6 +8216,9 @@ packages: utf-8-validate: optional: true + x402@0.7.3: + resolution: {integrity: sha512-8CIZsdMTOn52PjMH/ErVke9ebeZ7ErwiZ5FL3tN3Wny7Ynxs3LkuB/0q7IoccRLdVXA7f2lueYBJ2iDrElhXnA==} + xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -6569,8 +8240,8 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@2.8.0: - resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} + yaml@2.8.1: + resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} engines: {node: '>= 14.6'} hasBin: true @@ -6582,20 +8253,25 @@ packages: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} zod@3.25.71: resolution: {integrity: sha512-BsBc/NPk7h8WsUWYWYL+BajcJPY8YhjelaWu2NMLuzgraKAz4Lb4/6K11g9jpuDetjMiqhZ6YaexFLOC0Ogi3Q==} + zod@4.1.12: + resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==} + zustand@5.0.0: resolution: {integrity: sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==} engines: {node: '>=12.20.0'} @@ -6614,21 +8290,52 @@ packages: use-sync-external-store: optional: true + zustand@5.0.3: + resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + + zustand@5.0.8: + resolution: {integrity: sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + snapshots: '@adraffy/ens-normalize@1.11.0': {} '@alloc/quick-lru@5.2.0': {} - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.12 - '@jridgewell/trace-mapping': 0.3.29 - '@asamuzakjp/css-color@3.2.0': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 lru-cache: 10.4.3 @@ -6639,76 +8346,76 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.0': {} + '@babel/compat-data@7.28.4': {} - '@babel/core@7.28.0': + '@babel/core@7.28.4': dependencies: - '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.0 + '@babel/generator': 7.28.3 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) - '@babel/helpers': 7.27.6 - '@babel/parser': 7.28.0 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.4 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.0 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.1 + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.28.0': + '@babel/generator@7.28.3': dependencies: - '@babel/parser': 7.28.0 - '@babel/types': 7.28.0 - '@jridgewell/gen-mapping': 0.3.12 - '@jridgewell/trace-mapping': 0.3.29 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.28.0 + '@babel/types': 7.28.4 '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.28.0 + '@babel/compat-data': 7.28.4 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.25.1 + browserslist: 4.27.0 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.0)': + '@babel/helper-create-class-features-plugin@7.28.3(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.4 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.0)': + '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 - regexpu-core: 6.2.0 + regexpu-core: 6.4.0 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.0)': + '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - debug: 4.4.1 + debug: 4.4.3 lodash.debounce: 4.0.8 - resolve: 1.22.10 + resolve: 1.22.11 transitivePeerDependencies: - supports-color @@ -6716,55 +8423,55 @@ snapshots: '@babel/helper-member-expression-to-functions@7.27.1': dependencies: - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.0 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.0 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)': + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.28.0 + '@babel/types': 7.28.4 '@babel/helper-plugin-utils@7.27.1': {} - '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.0)': + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-wrap-function': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/helper-wrap-function': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.0)': + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.0 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color @@ -6774,608 +8481,673 @@ snapshots: '@babel/helper-validator-option@7.27.1': {} - '@babel/helper-wrap-function@7.27.1': + '@babel/helper-wrap-function@7.28.3': dependencies: '@babel/template': 7.27.2 - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.0 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/helpers@7.27.6': + '@babel/helpers@7.28.4': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.0 + '@babel/types': 7.28.4 - '@babel/parser@7.28.0': + '@babel/parser@7.28.4': dependencies: - '@babel/types': 7.28.0 + '@babel/types': 7.28.4 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.4) transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.0)': + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 - '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.0)': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.0) - '@babel/traverse': 7.28.0 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.4) + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.0) + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.4) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-block-scoping@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-block-scoping@7.28.4(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-static-block@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-class-static-block@7.28.3(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-classes@7.28.4(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-globals': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) - '@babel/traverse': 7.28.0 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 '@babel/template': 7.27.2 - '@babel/plugin-transform-destructuring@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-destructuring@7.28.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.4) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.0 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-object-rest-spread@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-object-rest-spread@7.28.4(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.0) - '@babel/traverse': 7.28.0 + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.4) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.4) + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.0)': + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-constant-elements@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-constant-elements@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.4) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/types': 7.28.0 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4) + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regenerator@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-regenerator@7.28.4(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.4) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.27.1 - '@babel/preset-env@7.28.0(@babel/core@7.28.0)': + '@babel/preset-env@7.28.3(@babel/core@7.28.4)': dependencies: - '@babel/compat-data': 7.28.0 - '@babel/core': 7.28.0 + '@babel/compat-data': 7.28.4 + '@babel/core': 7.28.4 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.0) - '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.0) - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-block-scoping': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-classes': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.0) - '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-regenerator': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.0) - babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.0) - babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.0) - babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.0) - core-js-compat: 3.43.0 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.3(@babel/core@7.28.4) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.4) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.4) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.4) + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-block-scoping': 7.28.4(@babel/core@7.28.4) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-class-static-block': 7.28.3(@babel/core@7.28.4) + '@babel/plugin-transform-classes': 7.28.4(@babel/core@7.28.4) + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.4) + '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.4) + '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-object-rest-spread': 7.28.4(@babel/core@7.28.4) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.4) + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-regenerator': 7.28.4(@babel/core@7.28.4) + '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.4) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.4) + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.4) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.4) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.4) + core-js-compat: 3.46.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.0)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/types': 7.28.0 + '@babel/types': 7.28.4 esutils: 2.0.3 - '@babel/preset-react@7.27.1(@babel/core@7.28.0)': + '@babel/preset-react@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.4) + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.28.4) transitivePeerDependencies: - supports-color - '@babel/preset-typescript@7.27.1(@babel/core@7.28.0)': + '@babel/preset-typescript@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.0) + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.4) transitivePeerDependencies: - supports-color - '@babel/runtime@7.27.6': {} + '@babel/runtime@7.28.4': {} '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.0 - '@babel/types': 7.28.0 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 - '@babel/traverse@7.28.0': + '@babel/traverse@7.28.4': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.0 + '@babel/generator': 7.28.3 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.0 + '@babel/parser': 7.28.4 '@babel/template': 7.27.2 - '@babel/types': 7.28.0 - debug: 4.4.1 + '@babel/types': 7.28.4 + debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.28.0': + '@babel/types@7.28.4': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@coinbase/cdp-sdk@1.38.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)': + '@base-org/account@1.1.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(zod@3.25.71)': + dependencies: + '@noble/hashes': 1.4.0 + clsx: 1.2.1 + eventemitter3: 5.0.1 + idb-keyval: 6.2.1 + ox: 0.6.9(typescript@5.8.3)(zod@3.25.71) + preact: 10.24.2 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zustand: 5.0.3(@types/react@19.2.2)(react@19.2.0)(use-sync-external-store@1.4.0(react@19.2.0)) + transitivePeerDependencies: + - '@types/react' + - bufferutil + - immer + - react + - typescript + - use-sync-external-store + - utf-8-validate + - zod + + '@base-org/account@1.1.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71)': + dependencies: + '@noble/hashes': 1.4.0 + clsx: 1.2.1 + eventemitter3: 5.0.1 + idb-keyval: 6.2.1 + ox: 0.6.9(typescript@5.8.3)(zod@3.25.71) + preact: 10.24.2 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zustand: 5.0.3(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + transitivePeerDependencies: + - '@types/react' + - bufferutil + - immer + - react + - typescript + - use-sync-external-store + - utf-8-validate + - zod + + '@coinbase/cdp-sdk@1.38.4(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: - '@solana/spl-token': 0.4.13(@solana/web3.js@1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@solana-program/system': 0.8.1(@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token': 0.6.0(@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) abitype: 1.0.6(typescript@5.8.3)(zod@3.25.71) - axios: 1.10.0 - axios-retry: 4.5.0(axios@1.10.0) - jose: 6.0.11 + axios: 1.12.2 + axios-retry: 4.5.0(axios@1.12.2) + jose: 6.1.0 md5: 2.3.0 uncrypto: 0.1.3 - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zod: 3.25.71 + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + - ws + + '@coinbase/cdp-sdk@1.38.4(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana-program/system': 0.8.1(@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token': 0.6.0(@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + abitype: 1.0.6(typescript@5.8.3)(zod@3.25.71) + axios: 1.12.2 + axios-retry: 4.5.0(axios@1.12.2) + jose: 6.1.0 + md5: 2.3.0 + uncrypto: 0.1.3 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) zod: 3.25.71 transitivePeerDependencies: - bufferutil @@ -7384,13 +9156,37 @@ snapshots: - fastestsmallesttextencoderdecoder - typescript - utf-8-validate + - ws + + '@coinbase/cdp-sdk@1.38.4(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana-program/system': 0.8.1(@solana/kit@3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token': 0.6.0(@solana/kit@3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana/kit': 3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + abitype: 1.0.6(typescript@5.8.3)(zod@3.25.71) + axios: 1.12.2 + axios-retry: 4.5.0(axios@1.12.2) + jose: 6.1.0 + md5: 2.3.0 + uncrypto: 0.1.3 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zod: 3.25.71 + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + - ws - '@coinbase/onchainkit@0.38.15(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(bufferutil@4.0.9)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71)': + '@coinbase/onchainkit@0.38.19(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(bufferutil@4.0.9)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@farcaster/frame-sdk': 0.0.60(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@farcaster/frame-wagmi-connector': 0.0.53(@farcaster/frame-sdk@0.0.60(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) - '@tanstack/react-query': 5.81.5(react@19.2.1) - '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@farcaster/frame-sdk': 0.1.12(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@farcaster/miniapp-wagmi-connector': 1.1.0(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@tanstack/react-query': 5.90.8(react@19.2.1) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) clsx: 2.1.1 graphql: 16.11.0 graphql-request: 6.1.0(graphql@16.11.0) @@ -7398,8 +9194,8 @@ snapshots: react: 19.2.1 react-dom: 19.2.1(react@19.2.1) tailwind-merge: 2.6.0 - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - wagmi: 2.15.6(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.2.1))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + wagmi: 2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -7409,6 +9205,7 @@ snapshots: - '@azure/storage-blob' - '@capacitor/preferences' - '@deno/kv' + - '@farcaster/miniapp-sdk' - '@netlify/blobs' - '@planetscale/database' - '@react-native-async-storage/async-storage' @@ -7416,6 +9213,7 @@ snapshots: - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -7439,17 +9237,91 @@ snapshots: eth-json-rpc-filters: 6.0.1 eventemitter3: 5.0.1 keccak: 3.0.4 - preact: 10.26.9 + preact: 10.27.2 sha.js: 2.4.12 transitivePeerDependencies: - supports-color - '@coinbase/wallet-sdk@4.3.3': + '@coinbase/wallet-sdk@4.3.6(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@noble/hashes': 1.8.0 + '@noble/hashes': 1.4.0 + clsx: 1.2.1 + eventemitter3: 5.0.1 + idb-keyval: 6.2.1 + ox: 0.6.9(typescript@5.8.3)(zod@3.25.71) + preact: 10.24.2 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zustand: 5.0.3(@types/react@19.2.2)(react@19.2.0)(use-sync-external-store@1.4.0(react@19.2.0)) + transitivePeerDependencies: + - '@types/react' + - bufferutil + - immer + - react + - typescript + - use-sync-external-store + - utf-8-validate + - zod + + '@coinbase/wallet-sdk@4.3.6(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71)': + dependencies: + '@noble/hashes': 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 - preact: 10.26.9 + idb-keyval: 6.2.1 + ox: 0.6.9(typescript@5.8.3)(zod@3.25.71) + preact: 10.24.2 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zustand: 5.0.3(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + transitivePeerDependencies: + - '@types/react' + - bufferutil + - immer + - react + - typescript + - use-sync-external-store + - utf-8-validate + - zod + + '@coinbase/x402@0.7.3(@solana/sysvars@5.0.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@coinbase/cdp-sdk': 1.38.4(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + x402: 0.7.3(@solana/sysvars@5.0.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + zod: 3.25.71 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@solana/sysvars' + - '@tanstack/query-core' + - '@tanstack/react-query' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - debug + - encoding + - fastestsmallesttextencoderdecoder + - immer + - ioredis + - react + - supports-color + - typescript + - uploadthing + - utf-8-validate + - ws '@craftamap/esbuild-plugin-html@0.9.0(bufferutil@4.0.9)(esbuild@0.25.5)(utf-8-validate@5.0.10)': dependencies: @@ -7462,21 +9334,16 @@ snapshots: - supports-color - utf-8-validate - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - optional: true - - '@csstools/color-helpers@5.0.2': {} + '@csstools/color-helpers@5.1.0': {} '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/css-color-parser@3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: - '@csstools/color-helpers': 5.0.2 + '@csstools/color-helpers': 5.1.0 '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 @@ -7487,22 +9354,22 @@ snapshots: '@csstools/css-tokenizer@3.0.4': {} - '@ecies/ciphers@0.2.3(@noble/ciphers@1.3.0)': + '@ecies/ciphers@0.2.4(@noble/ciphers@1.3.0)': dependencies: '@noble/ciphers': 1.3.0 - '@emnapi/core@1.4.3': + '@emnapi/core@1.6.0': dependencies: - '@emnapi/wasi-threads': 1.0.2 + '@emnapi/wasi-threads': 1.1.0 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.4.3': + '@emnapi/runtime@1.6.0': dependencies: tslib: 2.8.1 optional: true - '@emnapi/wasi-threads@1.0.2': + '@emnapi/wasi-threads@1.1.0': dependencies: tslib: 2.8.1 optional: true @@ -7510,7 +9377,7 @@ snapshots: '@es-joy/jsdoccomment@0.50.2': dependencies: '@types/estree': 1.0.8 - '@typescript-eslint/types': 8.35.1 + '@typescript-eslint/types': 8.46.2 comment-parser: 1.4.1 esquery: 1.6.0 jsdoc-type-pratt-parser: 4.1.0 @@ -7596,612 +9463,1090 @@ snapshots: '@esbuild/linux-ppc64@0.19.12': optional: true - '@esbuild/linux-ppc64@0.25.5': + '@esbuild/linux-ppc64@0.25.5': + optional: true + + '@esbuild/linux-riscv64@0.19.12': + optional: true + + '@esbuild/linux-riscv64@0.25.5': + optional: true + + '@esbuild/linux-s390x@0.19.12': + optional: true + + '@esbuild/linux-s390x@0.25.5': + optional: true + + '@esbuild/linux-x64@0.19.12': + optional: true + + '@esbuild/linux-x64@0.25.5': + optional: true + + '@esbuild/netbsd-arm64@0.25.5': + optional: true + + '@esbuild/netbsd-x64@0.19.12': + optional: true + + '@esbuild/netbsd-x64@0.25.5': + optional: true + + '@esbuild/openbsd-arm64@0.25.5': + optional: true + + '@esbuild/openbsd-x64@0.19.12': + optional: true + + '@esbuild/openbsd-x64@0.25.5': + optional: true + + '@esbuild/sunos-x64@0.19.12': + optional: true + + '@esbuild/sunos-x64@0.25.5': + optional: true + + '@esbuild/win32-arm64@0.19.12': + optional: true + + '@esbuild/win32-arm64@0.25.5': + optional: true + + '@esbuild/win32-ia32@0.19.12': + optional: true + + '@esbuild/win32-ia32@0.25.5': + optional: true + + '@esbuild/win32-x64@0.19.12': + optional: true + + '@esbuild/win32-x64@0.25.5': + optional: true + + '@eslint-community/eslint-utils@4.9.0(eslint@9.38.0(jiti@1.21.7))': + dependencies: + eslint: 9.38.0(jiti@1.21.7) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.1': + dependencies: + '@eslint/core': 0.16.0 + + '@eslint/core@0.16.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.38.0': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.0': + dependencies: + '@eslint/core': 0.16.0 + levn: 0.4.1 + + '@ethereumjs/common@3.2.0': + dependencies: + '@ethereumjs/util': 8.1.0 + crc-32: 1.2.2 + + '@ethereumjs/rlp@4.0.1': {} + + '@ethereumjs/tx@4.2.0': + dependencies: + '@ethereumjs/common': 3.2.0 + '@ethereumjs/rlp': 4.0.1 + '@ethereumjs/util': 8.1.0 + ethereum-cryptography: 2.2.1 + + '@ethereumjs/util@8.1.0': + dependencies: + '@ethereumjs/rlp': 4.0.1 + ethereum-cryptography: 2.2.1 + micro-ftch: 0.3.1 + + '@farcaster/frame-sdk@0.1.12(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + dependencies: + '@farcaster/miniapp-sdk': 0.2.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@farcaster/quick-auth': 0.0.8(typescript@5.8.3) + comlink: 4.4.2 + eventemitter3: 5.0.1 + ox: 0.4.4(typescript@5.8.3)(zod@3.25.71) + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + - zod + + '@farcaster/miniapp-core@0.4.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)': + dependencies: + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + ox: 0.4.4(typescript@5.8.3)(zod@3.25.71) + zod: 3.25.71 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + + '@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + dependencies: + '@farcaster/miniapp-core': 0.4.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@farcaster/quick-auth': 0.0.6(typescript@5.8.3) + comlink: 4.4.2 + eventemitter3: 5.0.1 + ox: 0.4.4(typescript@5.8.3)(zod@3.25.71) + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + - zod + + '@farcaster/miniapp-wagmi-connector@1.1.0(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))': + dependencies: + '@farcaster/miniapp-sdk': 0.2.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + + '@farcaster/quick-auth@0.0.6(typescript@5.8.3)': + dependencies: + jose: 5.10.0 + typescript: 5.8.3 + zod: 3.25.71 + + '@farcaster/quick-auth@0.0.8(typescript@5.8.3)': + dependencies: + jose: 5.10.0 + typescript: 5.8.3 + zod: 3.25.71 + + '@gemini-wallet/core@0.2.0(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))': + dependencies: + '@metamask/rpc-errors': 7.0.2 + eventemitter3: 5.0.1 + viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + transitivePeerDependencies: + - supports-color + + '@gemini-wallet/core@0.2.0(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))': + dependencies: + '@metamask/rpc-errors': 7.0.2 + eventemitter3: 5.0.1 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + transitivePeerDependencies: + - supports-color + + '@graphql-typed-document-node/core@3.2.0(graphql@16.11.0)': + dependencies: + graphql: 16.11.0 + + '@heroicons/react@2.2.0(react@19.2.1)': + dependencies: + react: 19.2.1 + + '@hono/node-server@1.19.5(hono@4.10.2)': + dependencies: + hono: 4.10.2 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@img/colour@1.0.0': + optional: true + + '@img/sharp-darwin-arm64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.3 + optional: true + + '@img/sharp-darwin-x64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.3 optional: true - '@esbuild/linux-riscv64@0.19.12': + '@img/sharp-libvips-darwin-arm64@1.2.3': optional: true - '@esbuild/linux-riscv64@0.25.5': + '@img/sharp-libvips-darwin-x64@1.2.3': optional: true - '@esbuild/linux-s390x@0.19.12': + '@img/sharp-libvips-linux-arm64@1.2.3': optional: true - '@esbuild/linux-s390x@0.25.5': + '@img/sharp-libvips-linux-arm@1.2.3': optional: true - '@esbuild/linux-x64@0.19.12': + '@img/sharp-libvips-linux-ppc64@1.2.3': optional: true - '@esbuild/linux-x64@0.25.5': + '@img/sharp-libvips-linux-s390x@1.2.3': optional: true - '@esbuild/netbsd-arm64@0.25.5': + '@img/sharp-libvips-linux-x64@1.2.3': optional: true - '@esbuild/netbsd-x64@0.19.12': + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': optional: true - '@esbuild/netbsd-x64@0.25.5': + '@img/sharp-libvips-linuxmusl-x64@1.2.3': optional: true - '@esbuild/openbsd-arm64@0.25.5': + '@img/sharp-linux-arm64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.3 optional: true - '@esbuild/openbsd-x64@0.19.12': + '@img/sharp-linux-arm@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.3 optional: true - '@esbuild/openbsd-x64@0.25.5': + '@img/sharp-linux-ppc64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.3 optional: true - '@esbuild/sunos-x64@0.19.12': + '@img/sharp-linux-s390x@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.3 optional: true - '@esbuild/sunos-x64@0.25.5': + '@img/sharp-linux-x64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.3 optional: true - '@esbuild/win32-arm64@0.19.12': + '@img/sharp-linuxmusl-arm64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 optional: true - '@esbuild/win32-arm64@0.25.5': + '@img/sharp-linuxmusl-x64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 optional: true - '@esbuild/win32-ia32@0.19.12': + '@img/sharp-wasm32@0.34.4': + dependencies: + '@emnapi/runtime': 1.6.0 optional: true - '@esbuild/win32-ia32@0.25.5': + '@img/sharp-win32-arm64@0.34.4': optional: true - '@esbuild/win32-x64@0.19.12': + '@img/sharp-win32-ia32@0.34.4': optional: true - '@esbuild/win32-x64@0.25.5': + '@img/sharp-win32-x64@0.34.4': optional: true - '@eslint-community/eslint-utils@4.7.0(eslint@9.30.1(jiti@1.21.7))': + '@isaacs/cliui@8.0.2': dependencies: - eslint: 9.30.1(jiti@1.21.7) - eslint-visitor-keys: 3.4.3 + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.2 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 - '@eslint-community/regexpp@4.12.1': {} + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 - '@eslint/config-array@0.21.0': + '@jridgewell/remapping@2.3.5': dependencies: - '@eslint/object-schema': 2.1.6 - debug: 4.4.1 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} - '@eslint/config-helpers@0.3.0': {} + '@jridgewell/sourcemap-codec@1.5.5': {} - '@eslint/core@0.14.0': + '@jridgewell/trace-mapping@0.3.31': dependencies: - '@types/json-schema': 7.0.15 + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@lit-labs/ssr-dom-shim@1.4.0': {} - '@eslint/core@0.15.1': + '@lit/reactive-element@2.1.1': dependencies: - '@types/json-schema': 7.0.15 + '@lit-labs/ssr-dom-shim': 1.4.0 - '@eslint/eslintrc@3.3.1': + '@metamask/eth-json-rpc-provider@1.0.1': dependencies: - ajv: 6.12.6 - debug: 4.4.1 - espree: 10.4.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 + '@metamask/json-rpc-engine': 7.3.3 + '@metamask/safe-event-emitter': 3.1.2 + '@metamask/utils': 5.0.2 transitivePeerDependencies: - supports-color - '@eslint/js@9.30.1': {} + '@metamask/json-rpc-engine@7.3.3': + dependencies: + '@metamask/rpc-errors': 6.4.0 + '@metamask/safe-event-emitter': 3.1.2 + '@metamask/utils': 8.5.0 + transitivePeerDependencies: + - supports-color - '@eslint/object-schema@2.1.6': {} + '@metamask/json-rpc-engine@8.0.2': + dependencies: + '@metamask/rpc-errors': 6.4.0 + '@metamask/safe-event-emitter': 3.1.2 + '@metamask/utils': 8.5.0 + transitivePeerDependencies: + - supports-color - '@eslint/plugin-kit@0.3.3': + '@metamask/json-rpc-middleware-stream@7.0.2': dependencies: - '@eslint/core': 0.15.1 - levn: 0.4.1 + '@metamask/json-rpc-engine': 8.0.2 + '@metamask/safe-event-emitter': 3.1.2 + '@metamask/utils': 8.5.0 + readable-stream: 3.6.2 + transitivePeerDependencies: + - supports-color - '@ethereumjs/common@3.2.0': + '@metamask/object-multiplex@2.1.0': dependencies: - '@ethereumjs/util': 8.1.0 - crc-32: 1.2.2 + once: 1.4.0 + readable-stream: 3.6.2 - '@ethereumjs/rlp@4.0.1': {} + '@metamask/onboarding@1.0.1': + dependencies: + bowser: 2.12.1 - '@ethereumjs/tx@4.2.0': + '@metamask/providers@16.1.0': dependencies: - '@ethereumjs/common': 3.2.0 - '@ethereumjs/rlp': 4.0.1 - '@ethereumjs/util': 8.1.0 - ethereum-cryptography: 2.2.1 + '@metamask/json-rpc-engine': 8.0.2 + '@metamask/json-rpc-middleware-stream': 7.0.2 + '@metamask/object-multiplex': 2.1.0 + '@metamask/rpc-errors': 6.4.0 + '@metamask/safe-event-emitter': 3.1.2 + '@metamask/utils': 8.5.0 + detect-browser: 5.3.0 + extension-port-stream: 3.0.0 + fast-deep-equal: 3.1.3 + is-stream: 2.0.1 + readable-stream: 3.6.2 + webextension-polyfill: 0.10.0 + transitivePeerDependencies: + - supports-color - '@ethereumjs/util@8.1.0': + '@metamask/rpc-errors@6.4.0': dependencies: - '@ethereumjs/rlp': 4.0.1 - ethereum-cryptography: 2.2.1 - micro-ftch: 0.3.1 + '@metamask/utils': 9.3.0 + fast-safe-stringify: 2.1.1 + transitivePeerDependencies: + - supports-color - '@farcaster/frame-core@0.1.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)': + '@metamask/rpc-errors@7.0.2': dependencies: - '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - ox: 0.4.4(typescript@5.8.3)(zod@3.25.71) - zod: 3.25.71 + '@metamask/utils': 11.8.1 + fast-safe-stringify: 2.1.1 transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate + - supports-color - '@farcaster/frame-sdk@0.0.60(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + '@metamask/safe-event-emitter@2.0.0': {} + + '@metamask/safe-event-emitter@3.1.2': {} + + '@metamask/sdk-analytics@0.0.5': dependencies: - '@farcaster/frame-core': 0.1.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@farcaster/quick-auth': 0.0.5(typescript@5.8.3) - comlink: 4.4.2 - eventemitter3: 5.0.1 - ox: 0.4.4(typescript@5.8.3)(zod@3.25.71) + openapi-fetch: 0.13.8 + + '@metamask/sdk-communication-layer@0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.16)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@metamask/sdk-analytics': 0.0.5 + bufferutil: 4.0.9 + cross-fetch: 4.1.0 + date-fns: 2.30.0 + debug: 4.3.4 + eciesjs: 0.4.16 + eventemitter2: 6.4.9 + readable-stream: 3.6.2 + socket.io-client: 4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + utf-8-validate: 5.0.10 + uuid: 8.3.2 + transitivePeerDependencies: + - supports-color + + '@metamask/sdk-install-modal-web@0.32.1': + dependencies: + '@paulmillr/qr': 0.2.1 + + '@metamask/sdk@0.33.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + dependencies: + '@babel/runtime': 7.28.4 + '@metamask/onboarding': 1.0.1 + '@metamask/providers': 16.1.0 + '@metamask/sdk-analytics': 0.0.5 + '@metamask/sdk-communication-layer': 0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.16)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@metamask/sdk-install-modal-web': 0.32.1 + '@paulmillr/qr': 0.2.1 + bowser: 2.12.1 + cross-fetch: 4.1.0 + debug: 4.3.4 + eciesjs: 0.4.16 + eth-rpc-errors: 4.0.3 + eventemitter2: 6.4.9 + obj-multiplex: 1.0.0 + pump: 3.0.3 + readable-stream: 3.6.2 + socket.io-client: 4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + tslib: 2.8.1 + util: 0.12.5 + uuid: 8.3.2 transitivePeerDependencies: - bufferutil - encoding - - typescript + - supports-color - utf-8-validate - - zod - '@farcaster/frame-wagmi-connector@0.0.53(@farcaster/frame-sdk@0.0.60(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))': - dependencies: - '@farcaster/frame-sdk': 0.0.60(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@metamask/superstruct@3.2.1': {} - '@farcaster/quick-auth@0.0.5(typescript@5.8.3)': + '@metamask/utils@11.8.1': dependencies: - jose: 5.10.0 - typescript: 5.8.3 - zod: 3.25.71 + '@ethereumjs/tx': 4.2.0 + '@metamask/superstruct': 3.2.1 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + '@types/debug': 4.1.12 + '@types/lodash': 4.17.20 + debug: 4.4.3 + lodash: 4.17.21 + pony-cause: 2.1.11 + semver: 7.7.3 + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color - '@graphql-typed-document-node/core@3.2.0(graphql@16.11.0)': + '@metamask/utils@5.0.2': dependencies: - graphql: 16.11.0 + '@ethereumjs/tx': 4.2.0 + '@types/debug': 4.1.12 + debug: 4.4.3 + semver: 7.7.3 + superstruct: 1.0.4 + transitivePeerDependencies: + - supports-color - '@heroicons/react@2.2.0(react@19.2.1)': + '@metamask/utils@8.5.0': dependencies: - react: 19.2.1 + '@ethereumjs/tx': 4.2.0 + '@metamask/superstruct': 3.2.1 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + '@types/debug': 4.1.12 + debug: 4.4.3 + pony-cause: 2.1.11 + semver: 7.7.3 + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color - '@hono/node-server@1.15.0(hono@4.8.3)': + '@metamask/utils@9.3.0': dependencies: - hono: 4.8.3 - - '@humanfs/core@0.19.1': {} + '@ethereumjs/tx': 4.2.0 + '@metamask/superstruct': 3.2.1 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + '@types/debug': 4.1.12 + debug: 4.4.3 + pony-cause: 2.1.11 + semver: 7.7.3 + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color - '@humanfs/node@0.16.6': + '@napi-rs/wasm-runtime@0.2.12': dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 + '@emnapi/core': 1.6.0 + '@emnapi/runtime': 1.6.0 + '@tybys/wasm-util': 0.10.1 + optional: true - '@humanwhocodes/module-importer@1.0.1': {} + '@next/env@15.5.7': {} - '@humanwhocodes/retry@0.3.1': {} + '@next/env@16.0.7': {} - '@humanwhocodes/retry@0.4.3': {} + '@next/eslint-plugin-next@15.1.9': + dependencies: + fast-glob: 3.3.1 - '@img/sharp-darwin-arm64@0.34.2': - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.1.0 - optional: true + '@next/eslint-plugin-next@16.0.7': + dependencies: + fast-glob: 3.3.1 - '@img/sharp-darwin-x64@0.34.2': - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.1.0 + '@next/swc-darwin-arm64@15.5.7': optional: true - '@img/sharp-libvips-darwin-arm64@1.1.0': + '@next/swc-darwin-arm64@16.0.7': optional: true - '@img/sharp-libvips-darwin-x64@1.1.0': + '@next/swc-darwin-x64@15.5.7': optional: true - '@img/sharp-libvips-linux-arm64@1.1.0': + '@next/swc-darwin-x64@16.0.7': optional: true - '@img/sharp-libvips-linux-arm@1.1.0': + '@next/swc-linux-arm64-gnu@15.5.7': optional: true - '@img/sharp-libvips-linux-ppc64@1.1.0': + '@next/swc-linux-arm64-gnu@16.0.7': optional: true - '@img/sharp-libvips-linux-s390x@1.1.0': + '@next/swc-linux-arm64-musl@15.5.7': optional: true - '@img/sharp-libvips-linux-x64@1.1.0': + '@next/swc-linux-arm64-musl@16.0.7': optional: true - '@img/sharp-libvips-linuxmusl-arm64@1.1.0': + '@next/swc-linux-x64-gnu@15.5.7': optional: true - '@img/sharp-libvips-linuxmusl-x64@1.1.0': + '@next/swc-linux-x64-gnu@16.0.7': optional: true - '@img/sharp-linux-arm64@0.34.2': - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.1.0 + '@next/swc-linux-x64-musl@15.5.7': optional: true - '@img/sharp-linux-arm@0.34.2': - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.1.0 + '@next/swc-linux-x64-musl@16.0.7': optional: true - '@img/sharp-linux-s390x@0.34.2': - optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.1.0 + '@next/swc-win32-arm64-msvc@15.5.7': optional: true - '@img/sharp-linux-x64@0.34.2': - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.1.0 + '@next/swc-win32-arm64-msvc@16.0.7': optional: true - '@img/sharp-linuxmusl-arm64@0.34.2': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 + '@next/swc-win32-x64-msvc@15.5.7': optional: true - '@img/sharp-linuxmusl-x64@0.34.2': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.1.0 + '@next/swc-win32-x64-msvc@16.0.7': optional: true - '@img/sharp-wasm32@0.34.2': + '@noble/ciphers@1.2.1': {} + + '@noble/ciphers@1.3.0': {} + + '@noble/curves@1.4.2': + dependencies: + '@noble/hashes': 1.4.0 + + '@noble/curves@1.8.0': + dependencies: + '@noble/hashes': 1.7.0 + + '@noble/curves@1.8.1': + dependencies: + '@noble/hashes': 1.7.1 + + '@noble/curves@1.9.1': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/curves@1.9.2': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/curves@1.9.7': dependencies: - '@emnapi/runtime': 1.4.3 - optional: true + '@noble/hashes': 1.8.0 - '@img/sharp-win32-arm64@0.34.2': - optional: true + '@noble/hashes@1.4.0': {} - '@img/sharp-win32-ia32@0.34.2': - optional: true + '@noble/hashes@1.7.0': {} - '@img/sharp-win32-x64@0.34.2': - optional: true + '@noble/hashes@1.7.1': {} - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 + '@noble/hashes@1.8.0': {} - '@jridgewell/gen-mapping@0.3.12': + '@nodelib/fs.scandir@2.1.5': dependencies: - '@jridgewell/sourcemap-codec': 1.5.4 - '@jridgewell/trace-mapping': 0.3.29 - - '@jridgewell/resolve-uri@3.1.2': {} + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 - '@jridgewell/sourcemap-codec@1.5.4': {} + '@nodelib/fs.stat@2.0.5': {} - '@jridgewell/trace-mapping@0.3.29': + '@nodelib/fs.walk@1.2.8': dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.4 + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 - '@jridgewell/trace-mapping@0.3.9': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.4 - optional: true + '@nolyfill/is-core-module@1.0.39': {} - '@lit-labs/ssr-dom-shim@1.3.0': {} + '@paulmillr/qr@0.2.1': {} - '@lit/reactive-element@2.1.0': - dependencies: - '@lit-labs/ssr-dom-shim': 1.3.0 + '@pkgjs/parseargs@0.11.0': + optional: true - '@metamask/eth-json-rpc-provider@1.0.1': - dependencies: - '@metamask/json-rpc-engine': 7.3.3 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 5.0.2 - transitivePeerDependencies: - - supports-color + '@pkgr/core@0.2.9': {} - '@metamask/json-rpc-engine@7.3.3': + '@reown/appkit-common@1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.22.4)': dependencies: - '@metamask/rpc-errors': 6.4.0 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 8.5.0 + big.js: 6.2.2 + dayjs: 1.11.13 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.22.4) transitivePeerDependencies: - - supports-color + - bufferutil + - typescript + - utf-8-validate + - zod - '@metamask/json-rpc-engine@8.0.2': + '@reown/appkit-common@1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@metamask/rpc-errors': 6.4.0 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 8.5.0 + big.js: 6.2.2 + dayjs: 1.11.13 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - - supports-color + - bufferutil + - typescript + - utf-8-validate + - zod - '@metamask/json-rpc-middleware-stream@7.0.2': + '@reown/appkit-controllers@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@metamask/json-rpc-engine': 8.0.2 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 8.5.0 - readable-stream: 3.6.2 + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.0) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - - supports-color - - '@metamask/object-multiplex@2.1.0': - dependencies: - once: 1.4.0 - readable-stream: 3.6.2 - - '@metamask/onboarding@1.0.1': - dependencies: - bowser: 2.11.0 + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - zod - '@metamask/providers@16.1.0': + '@reown/appkit-controllers@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@metamask/json-rpc-engine': 8.0.2 - '@metamask/json-rpc-middleware-stream': 7.0.2 - '@metamask/object-multiplex': 2.1.0 - '@metamask/rpc-errors': 6.4.0 - '@metamask/safe-event-emitter': 3.1.2 - '@metamask/utils': 8.5.0 - detect-browser: 5.3.0 - extension-port-stream: 3.0.0 - fast-deep-equal: 3.1.3 - is-stream: 2.0.1 - readable-stream: 3.6.2 - webextension-polyfill: 0.10.0 + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - - supports-color + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - zod - '@metamask/rpc-errors@6.4.0': + '@reown/appkit-controllers@1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@metamask/utils': 9.3.0 - fast-safe-stringify: 2.1.1 + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + valtio: 1.13.2(react@19.2.1) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - - supports-color - - '@metamask/safe-event-emitter@2.0.0': {} - - '@metamask/safe-event-emitter@3.1.2': {} + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - zod - '@metamask/sdk-communication-layer@0.32.0(cross-fetch@4.1.0)(eciesjs@0.4.15)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@reown/appkit-pay@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - bufferutil: 4.0.9 - cross-fetch: 4.1.0 - date-fns: 2.30.0 - debug: 4.4.1 - eciesjs: 0.4.15 - eventemitter2: 6.4.9 - readable-stream: 3.6.2 - socket.io-client: 4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) - utf-8-validate: 5.0.10 - uuid: 8.3.2 + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.0))(zod@3.25.71) + lit: 3.3.0 + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.0) transitivePeerDependencies: - - supports-color - - '@metamask/sdk-install-modal-web@0.32.0': - dependencies: - '@paulmillr/qr': 0.2.1 + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - zod - '@metamask/sdk@0.32.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + '@reown/appkit-pay@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@babel/runtime': 7.27.6 - '@metamask/onboarding': 1.0.1 - '@metamask/providers': 16.1.0 - '@metamask/sdk-communication-layer': 0.32.0(cross-fetch@4.1.0)(eciesjs@0.4.15)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@metamask/sdk-install-modal-web': 0.32.0 - '@paulmillr/qr': 0.2.1 - bowser: 2.11.0 - cross-fetch: 4.1.0 - debug: 4.4.1 - eciesjs: 0.4.15 - eth-rpc-errors: 4.0.3 - eventemitter2: 6.4.9 - obj-multiplex: 1.0.0 - pump: 3.0.3 - readable-stream: 3.6.2 - socket.io-client: 4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) - tslib: 2.8.1 - util: 0.12.5 - uuid: 8.3.2 + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@3.25.71) + lit: 3.3.0 + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch - bufferutil + - db0 - encoding - - supports-color + - ioredis + - react + - typescript + - uploadthing - utf-8-validate + - zod - '@metamask/superstruct@3.2.1': {} - - '@metamask/utils@5.0.2': + '@reown/appkit-pay@1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@ethereumjs/tx': 4.2.0 - '@types/debug': 4.1.12 - debug: 4.4.1 - semver: 7.7.2 - superstruct: 1.0.4 + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-utils': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.1))(zod@3.25.71) + lit: 3.3.0 + valtio: 1.13.2(react@19.2.1) transitivePeerDependencies: - - supports-color + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - zod - '@metamask/utils@8.5.0': + '@reown/appkit-polyfills@1.7.8': dependencies: - '@ethereumjs/tx': 4.2.0 - '@metamask/superstruct': 3.2.1 - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 - '@types/debug': 4.1.12 - debug: 4.4.1 - pony-cause: 2.1.11 - semver: 7.7.2 - uuid: 9.0.1 - transitivePeerDependencies: - - supports-color + buffer: 6.0.3 - '@metamask/utils@9.3.0': + '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.0))(zod@3.25.71)': dependencies: - '@ethereumjs/tx': 4.2.0 - '@metamask/superstruct': 3.2.1 - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 - '@types/debug': 4.1.12 - debug: 4.4.1 - pony-cause: 2.1.11 - semver: 7.7.2 - uuid: 9.0.1 + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.0))(zod@3.25.71) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + lit: 3.3.0 transitivePeerDependencies: - - supports-color - - '@napi-rs/wasm-runtime@0.2.11': - dependencies: - '@emnapi/core': 1.4.3 - '@emnapi/runtime': 1.4.3 - '@tybys/wasm-util': 0.9.0 - optional: true - - '@next/env@15.3.4': {} - - '@next/env@15.4.0-canary.113': {} - - '@next/eslint-plugin-next@15.1.7': - dependencies: - fast-glob: 3.3.1 - - '@next/swc-darwin-arm64@15.3.4': - optional: true - - '@next/swc-darwin-arm64@15.4.0-canary.113': - optional: true - - '@next/swc-darwin-x64@15.3.4': - optional: true - - '@next/swc-darwin-x64@15.4.0-canary.113': - optional: true - - '@next/swc-linux-arm64-gnu@15.3.4': - optional: true - - '@next/swc-linux-arm64-gnu@15.4.0-canary.113': - optional: true - - '@next/swc-linux-arm64-musl@15.3.4': - optional: true - - '@next/swc-linux-arm64-musl@15.4.0-canary.113': - optional: true - - '@next/swc-linux-x64-gnu@15.3.4': - optional: true - - '@next/swc-linux-x64-gnu@15.4.0-canary.113': - optional: true - - '@next/swc-linux-x64-musl@15.3.4': - optional: true - - '@next/swc-linux-x64-musl@15.4.0-canary.113': - optional: true - - '@next/swc-win32-arm64-msvc@15.3.4': - optional: true - - '@next/swc-win32-arm64-msvc@15.4.0-canary.113': - optional: true - - '@next/swc-win32-x64-msvc@15.3.4': - optional: true - - '@next/swc-win32-x64-msvc@15.4.0-canary.113': - optional: true - - '@noble/ciphers@1.2.1': {} - - '@noble/ciphers@1.3.0': {} - - '@noble/curves@1.4.2': - dependencies: - '@noble/hashes': 1.4.0 - - '@noble/curves@1.8.0': - dependencies: - '@noble/hashes': 1.7.0 - - '@noble/curves@1.8.1': - dependencies: - '@noble/hashes': 1.7.1 - - '@noble/curves@1.9.2': - dependencies: - '@noble/hashes': 1.8.0 - - '@noble/hashes@1.4.0': {} - - '@noble/hashes@1.7.0': {} - - '@noble/hashes@1.7.1': {} - - '@noble/hashes@1.8.0': {} + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - valtio + - zod - '@nodelib/fs.scandir@2.1.5': + '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@3.25.71)': dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@3.25.71) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + lit: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - valtio + - zod - '@nodelib/fs.walk@1.2.8': + '@reown/appkit-scaffold-ui@1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.1))(zod@3.25.71)': dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.1 - - '@nolyfill/is-core-module@1.0.39': {} - - '@paulmillr/qr@0.2.1': {} - - '@pkgjs/parseargs@0.11.0': - optional: true - - '@pkgr/core@0.2.7': {} + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-utils': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.1))(zod@3.25.71) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + lit: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - valtio + - zod - '@reown/appkit-common@1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.22.4)': + '@reown/appkit-ui@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - big.js: 6.2.2 - dayjs: 1.11.13 - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.22.4) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + lit: 3.3.0 + qrcode: 1.5.3 transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch - bufferutil + - db0 + - encoding + - ioredis + - react - typescript + - uploadthing - utf-8-validate - zod - '@reown/appkit-common@1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + '@reown/appkit-ui@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - big.js: 6.2.2 - dayjs: 1.11.13 - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + lit: 3.3.0 + qrcode: 1.5.3 transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch - bufferutil + - db0 + - encoding + - ioredis + - react - typescript + - uploadthing - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + '@reown/appkit-ui@1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - valtio: 1.13.2(@types/react@19.1.8)(react@19.2.1) - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + lit: 3.3.0 + qrcode: 1.5.3 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -8217,6 +10562,7 @@ snapshots: - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -8229,14 +10575,16 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-pay@1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + '@reown/appkit-utils@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.0))(zod@3.25.71)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-ui': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-utils': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.8)(react@19.2.1))(zod@3.25.71) - lit: 3.3.0 - valtio: 1.13.2(@types/react@19.1.8)(react@19.2.1) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-polyfills': 1.7.8 + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@walletconnect/logger': 2.1.2 + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.0) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -8252,6 +10600,7 @@ snapshots: - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -8264,18 +10613,16 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-polyfills@1.7.8': - dependencies: - buffer: 6.0.3 - - '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.8)(react@19.2.1))(zod@3.25.71)': + '@reown/appkit-utils@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@3.25.71)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-ui': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-utils': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.8)(react@19.2.1))(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - lit: 3.3.0 + '@walletconnect/logger': 2.1.2 + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -8291,6 +10638,7 @@ snapshots: - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -8301,16 +10649,18 @@ snapshots: - typescript - uploadthing - utf-8-validate - - valtio - zod - '@reown/appkit-ui@1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + '@reown/appkit-utils@1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.1))(zod@3.25.71)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - lit: 3.3.0 - qrcode: 1.5.3 + '@walletconnect/logger': 2.1.2 + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + valtio: 1.13.2(react@19.2.1) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -8326,6 +10676,7 @@ snapshots: - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -8338,16 +10689,32 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.8)(react@19.2.1))(zod@3.25.71)': + '@reown/appkit-wallet@1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)': + dependencies: + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.22.4) + '@reown/appkit-polyfills': 1.7.8 + '@walletconnect/logger': 2.1.2 + zod: 3.22.4 + transitivePeerDependencies: + - bufferutil + - typescript + - utf-8-validate + + '@reown/appkit@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-pay': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) '@reown/appkit-polyfills': 1.7.8 + '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.0))(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.0))(zod@3.25.71) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@walletconnect/logger': 2.1.2 + '@walletconnect/types': 2.21.0 '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - valtio: 1.13.2(@types/react@19.1.8)(react@19.2.1) - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + bs58: 6.0.0 + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.0) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -8363,6 +10730,7 @@ snapshots: - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -8375,32 +10743,64 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-wallet@1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)': + '@reown/appkit@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.22.4) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-pay': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) '@reown/appkit-polyfills': 1.7.8 - '@walletconnect/logger': 2.1.2 - zod: 3.22.4 + '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@3.25.71) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@walletconnect/types': 2.21.0 + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + bs58: 6.0.0 + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch - bufferutil + - db0 + - encoding + - ioredis + - react - typescript + - uploadthing - utf-8-validate + - zod - '@reown/appkit@1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + '@reown/appkit@1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-controllers': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-pay': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-controllers': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-pay': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.8)(react@19.2.1))(zod@3.25.71) - '@reown/appkit-ui': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@reown/appkit-utils': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.8)(react@19.2.1))(zod@3.25.71) + '@reown/appkit-scaffold-ui': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.1))(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit-utils': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.1))(zod@3.25.71) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) '@walletconnect/types': 2.21.0 '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) bs58: 6.0.0 - valtio: 1.13.2(@types/react@19.1.8)(react@19.2.1) - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + valtio: 1.13.2(react@19.2.1) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -8416,6 +10816,7 @@ snapshots: - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -8428,69 +10829,75 @@ snapshots: - utf-8-validate - zod - '@rollup/rollup-android-arm-eabi@4.44.1': + '@rollup/rollup-android-arm-eabi@4.52.5': + optional: true + + '@rollup/rollup-android-arm64@4.52.5': + optional: true + + '@rollup/rollup-darwin-arm64@4.52.5': optional: true - '@rollup/rollup-android-arm64@4.44.1': + '@rollup/rollup-darwin-x64@4.52.5': optional: true - '@rollup/rollup-darwin-arm64@4.44.1': + '@rollup/rollup-freebsd-arm64@4.52.5': optional: true - '@rollup/rollup-darwin-x64@4.44.1': + '@rollup/rollup-freebsd-x64@4.52.5': optional: true - '@rollup/rollup-freebsd-arm64@4.44.1': + '@rollup/rollup-linux-arm-gnueabihf@4.52.5': optional: true - '@rollup/rollup-freebsd-x64@4.44.1': + '@rollup/rollup-linux-arm-musleabihf@4.52.5': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.44.1': + '@rollup/rollup-linux-arm64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.44.1': + '@rollup/rollup-linux-arm64-musl@4.52.5': optional: true - '@rollup/rollup-linux-arm64-gnu@4.44.1': + '@rollup/rollup-linux-loong64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-arm64-musl@4.44.1': + '@rollup/rollup-linux-ppc64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.44.1': + '@rollup/rollup-linux-riscv64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.44.1': + '@rollup/rollup-linux-riscv64-musl@4.52.5': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.44.1': + '@rollup/rollup-linux-s390x-gnu@4.52.5': optional: true - '@rollup/rollup-linux-riscv64-musl@4.44.1': + '@rollup/rollup-linux-x64-gnu@4.52.5': optional: true - '@rollup/rollup-linux-s390x-gnu@4.44.1': + '@rollup/rollup-linux-x64-musl@4.52.5': optional: true - '@rollup/rollup-linux-x64-gnu@4.44.1': + '@rollup/rollup-openharmony-arm64@4.52.5': optional: true - '@rollup/rollup-linux-x64-musl@4.44.1': + '@rollup/rollup-win32-arm64-msvc@4.52.5': optional: true - '@rollup/rollup-win32-arm64-msvc@4.44.1': + '@rollup/rollup-win32-ia32-msvc@4.52.5': optional: true - '@rollup/rollup-win32-ia32-msvc@4.44.1': + '@rollup/rollup-win32-x64-gnu@4.52.5': optional: true - '@rollup/rollup-win32-x64-msvc@4.44.1': + '@rollup/rollup-win32-x64-msvc@4.52.5': optional: true '@rtsao/scc@1.1.0': {} - '@rushstack/eslint-patch@1.12.0': {} + '@rushstack/eslint-patch@1.14.0': {} '@safe-global/safe-apps-provider@0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: @@ -8505,7 +10912,7 @@ snapshots: '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: '@safe-global/safe-gateway-typescript-sdk': 3.23.1 - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - bufferutil - typescript @@ -8532,7 +10939,7 @@ snapshots: '@scure/bip32@1.7.0': dependencies: - '@noble/curves': 1.9.2 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 @@ -8553,18 +10960,105 @@ snapshots: '@socket.io/component-emitter@3.1.2': {} - '@solana-program/compute-budget@0.11.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + '@solana-program/compute-budget@0.11.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/compute-budget@0.11.0(@solana/kit@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/compute-budget@0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/compute-budget@0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/system@0.8.1(@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/system@0.8.1(@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/system@0.8.1(@solana/kit@3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': + dependencies: + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/sysvars': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + + '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': dependencies: - '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/sysvars': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + + '@solana-program/token-2022@0.6.1(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': + dependencies: + '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/sysvars': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana-program/token-2022@0.6.1(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': + '@solana-program/token-2022@0.6.1(@solana/kit@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(typescript@5.8.3))': dependencies: - '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/kit': 5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/sysvars': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana-program/token@0.9.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + '@solana-program/token@0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/token@0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/token@0.6.0(@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/token@0.6.0(@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/token@0.6.0(@solana/kit@3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/token@0.9.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/token@0.9.0(@solana/kit@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: - '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/kit': 5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana/accounts@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec': 2.3.0(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/accounts@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder '@solana/accounts@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: @@ -8578,6 +11072,28 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/addresses@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/assertions': 2.3.0(typescript@5.8.3) + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/nominal-types': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/addresses@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/assertions': 3.0.3(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/addresses@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/assertions': 5.0.0(typescript@5.8.3) @@ -8589,35 +11105,33 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/assertions@5.0.0(typescript@5.8.3)': + '@solana/assertions@2.3.0(typescript@5.8.3)': dependencies: - '@solana/errors': 5.0.0(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) typescript: 5.8.3 - '@solana/buffer-layout-utils@0.2.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)': + '@solana/assertions@3.0.3(typescript@5.8.3)': dependencies: - '@solana/buffer-layout': 4.0.1 - '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - bigint-buffer: 1.1.5 - bignumber.js: 9.3.0 - transitivePeerDependencies: - - bufferutil - - encoding - - typescript - - utf-8-validate + '@solana/errors': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + + '@solana/assertions@5.0.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 5.0.0(typescript@5.8.3) + typescript: 5.8.3 '@solana/buffer-layout@4.0.1': dependencies: buffer: 6.0.3 - '@solana/codecs-core@2.0.0-rc.1(typescript@5.8.3)': + '@solana/codecs-core@2.3.0(typescript@5.8.3)': dependencies: - '@solana/errors': 2.0.0-rc.1(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) typescript: 5.8.3 - '@solana/codecs-core@2.1.1(typescript@5.8.3)': + '@solana/codecs-core@3.0.3(typescript@5.8.3)': dependencies: - '@solana/errors': 2.1.1(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) typescript: 5.8.3 '@solana/codecs-core@5.0.0(typescript@5.8.3)': @@ -8625,11 +11139,18 @@ snapshots: '@solana/errors': 5.0.0(typescript@5.8.3) typescript: 5.8.3 - '@solana/codecs-data-structures@2.0.0-rc.1(typescript@5.8.3)': + '@solana/codecs-data-structures@2.3.0(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-numbers': 2.3.0(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + + '@solana/codecs-data-structures@3.0.3(typescript@5.8.3)': dependencies: - '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.8.3) - '@solana/errors': 2.0.0-rc.1(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) typescript: 5.8.3 '@solana/codecs-data-structures@5.0.0(typescript@5.8.3)': @@ -8639,16 +11160,16 @@ snapshots: '@solana/errors': 5.0.0(typescript@5.8.3) typescript: 5.8.3 - '@solana/codecs-numbers@2.0.0-rc.1(typescript@5.8.3)': + '@solana/codecs-numbers@2.3.0(typescript@5.8.3)': dependencies: - '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) - '@solana/errors': 2.0.0-rc.1(typescript@5.8.3) + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) typescript: 5.8.3 - '@solana/codecs-numbers@2.1.1(typescript@5.8.3)': + '@solana/codecs-numbers@3.0.3(typescript@5.8.3)': dependencies: - '@solana/codecs-core': 2.1.1(typescript@5.8.3) - '@solana/errors': 2.1.1(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) typescript: 5.8.3 '@solana/codecs-numbers@5.0.0(typescript@5.8.3)': @@ -8657,11 +11178,19 @@ snapshots: '@solana/errors': 5.0.0(typescript@5.8.3) typescript: 5.8.3 - '@solana/codecs-strings@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + '@solana/codecs-strings@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-numbers': 2.3.0(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + fastestsmallesttextencoderdecoder: 1.0.22 + typescript: 5.8.3 + + '@solana/codecs-strings@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: - '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.8.3) - '@solana/errors': 2.0.0-rc.1(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) fastestsmallesttextencoderdecoder: 1.0.22 typescript: 5.8.3 @@ -8673,13 +11202,24 @@ snapshots: fastestsmallesttextencoderdecoder: 1.0.22 typescript: 5.8.3 - '@solana/codecs@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + '@solana/codecs@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-data-structures': 2.3.0(typescript@5.8.3) + '@solana/codecs-numbers': 2.3.0(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/options': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/codecs@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: - '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-data-structures': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-strings': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/options': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-data-structures': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/options': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder @@ -8695,16 +11235,16 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/errors@2.0.0-rc.1(typescript@5.8.3)': + '@solana/errors@2.3.0(typescript@5.8.3)': dependencies: - chalk: 5.4.1 - commander: 12.1.0 + chalk: 5.6.2 + commander: 14.0.1 typescript: 5.8.3 - '@solana/errors@2.1.1(typescript@5.8.3)': + '@solana/errors@3.0.3(typescript@5.8.3)': dependencies: - chalk: 5.4.1 - commander: 13.1.0 + chalk: 5.6.2 + commander: 14.0.0 typescript: 5.8.3 '@solana/errors@5.0.0(typescript@5.8.3)': @@ -8713,14 +11253,41 @@ snapshots: commander: 14.0.1 typescript: 5.8.3 + '@solana/fast-stable-stringify@2.3.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@solana/fast-stable-stringify@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/fast-stable-stringify@5.0.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/functional@2.3.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@solana/functional@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/functional@5.0.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/instruction-plans@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/instructions': 3.0.3(typescript@5.8.3) + '@solana/promises': 3.0.3(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/instruction-plans@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) @@ -8732,24 +11299,186 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/instructions@5.0.0(typescript@5.8.3)': - dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.8.3) - '@solana/errors': 5.0.0(typescript@5.8.3) + '@solana/instructions@2.3.0(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + + '@solana/instructions@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + + '@solana/instructions@5.0.0(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 5.0.0(typescript@5.8.3) + '@solana/errors': 5.0.0(typescript@5.8.3) + typescript: 5.8.3 + + '@solana/keys@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/assertions': 2.3.0(typescript@5.8.3) + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/nominal-types': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/keys@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/assertions': 3.0.3(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/keys@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/assertions': 5.0.0(typescript@5.8.3) + '@solana/codecs-core': 5.0.0(typescript@5.8.3) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 5.0.0(typescript@5.8.3) + '@solana/nominal-types': 5.0.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/instructions': 2.3.0(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/programs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/signers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/sysvars': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/instructions': 2.3.0(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/programs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/signers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/sysvars': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/accounts': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/instruction-plans': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/instructions': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/programs': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/signers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/sysvars': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-confirmation': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/accounts': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/instruction-plans': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/instructions': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/programs': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/signers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/sysvars': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-confirmation': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws - '@solana/keys@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': - dependencies: - '@solana/assertions': 5.0.0(typescript@5.8.3) - '@solana/codecs-core': 5.0.0(typescript@5.8.3) - '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/errors': 5.0.0(typescript@5.8.3) - '@solana/nominal-types': 5.0.0(typescript@5.8.3) + '@solana/kit@3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/accounts': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/instruction-plans': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/instructions': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/programs': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-subscriptions': 3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/signers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/sysvars': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-confirmation': 3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder + - ws - '@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -8763,11 +11492,11 @@ snapshots: '@solana/rpc': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/rpc-parsed-types': 5.0.0(typescript@5.8.3) '@solana/rpc-spec-types': 5.0.0(typescript@5.8.3) - '@solana/rpc-subscriptions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/signers': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/sysvars': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/transaction-confirmation': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) typescript: 5.8.3 @@ -8775,7 +11504,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/kit@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -8789,11 +11518,11 @@ snapshots: '@solana/rpc': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/rpc-parsed-types': 5.0.0(typescript@5.8.3) '@solana/rpc-spec-types': 5.0.0(typescript@5.8.3) - '@solana/rpc-subscriptions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/signers': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/sysvars': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/transaction-confirmation': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': 5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) typescript: 5.8.3 @@ -8801,17 +11530,36 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/nominal-types@2.3.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@solana/nominal-types@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/nominal-types@5.0.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 - '@solana/options@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + '@solana/options@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-data-structures': 2.3.0(typescript@5.8.3) + '@solana/codecs-numbers': 2.3.0(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/options@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: - '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-data-structures': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-strings': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/errors': 2.0.0-rc.1(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-data-structures': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder @@ -8827,6 +11575,22 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/programs@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/programs@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/programs@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -8835,10 +11599,52 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/promises@2.3.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@solana/promises@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/promises@5.0.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/rpc-api@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec': 2.3.0(typescript@5.8.3) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc-api@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-transformers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc-api@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -8856,20 +11662,74 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc-parsed-types@2.3.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@solana/rpc-parsed-types@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/rpc-parsed-types@5.0.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/rpc-spec-types@2.3.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@solana/rpc-spec-types@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/rpc-spec-types@5.0.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/rpc-spec@2.3.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + + '@solana/rpc-spec@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + '@solana/rpc-spec@5.0.0(typescript@5.8.3)': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) '@solana/rpc-spec-types': 5.0.0(typescript@5.8.3) typescript: 5.8.3 + '@solana/rpc-subscriptions-api@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.8.3) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc-subscriptions-api@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-transformers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc-subscriptions-api@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -8883,14 +11743,59 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-subscriptions-channel-websocket@5.0.0(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.8.3) + '@solana/subscribable': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + + '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.8.3) + '@solana/subscribable': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + + '@solana/rpc-subscriptions-channel-websocket@3.0.3(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/rpc-subscriptions-spec': 3.0.3(typescript@5.8.3) + '@solana/subscribable': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + ws: 7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10) + + '@solana/rpc-subscriptions-channel-websocket@3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/rpc-subscriptions-spec': 3.0.3(typescript@5.8.3) + '@solana/subscribable': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + + '@solana/rpc-subscriptions-channel-websocket@3.0.3(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/rpc-subscriptions-spec': 3.0.3(typescript@5.8.3) + '@solana/subscribable': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + + '@solana/rpc-subscriptions-channel-websocket@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) '@solana/functional': 5.0.0(typescript@5.8.3) '@solana/rpc-subscriptions-spec': 5.0.0(typescript@5.8.3) '@solana/subscribable': 5.0.0(typescript@5.8.3) typescript: 5.8.3 - ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@solana/rpc-subscriptions-channel-websocket@5.0.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: @@ -8901,6 +11806,22 @@ snapshots: typescript: 5.8.3 ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@solana/rpc-subscriptions-spec@2.3.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/promises': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + '@solana/subscribable': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + + '@solana/rpc-subscriptions-spec@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/promises': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/subscribable': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + '@solana/rpc-subscriptions-spec@5.0.0(typescript@5.8.3)': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) @@ -8909,7 +11830,97 @@ snapshots: '@solana/subscribable': 5.0.0(typescript@5.8.3) typescript: 5.8.3 - '@solana/rpc-subscriptions@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/fast-stable-stringify': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/promises': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-subscriptions-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.8.3) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/subscribable': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/fast-stable-stringify': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/promises': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-subscriptions-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.8.3) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/subscribable': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/rpc-subscriptions@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/fast-stable-stringify': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/promises': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-subscriptions-api': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions-channel-websocket': 3.0.3(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-transformers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/subscribable': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/rpc-subscriptions@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/fast-stable-stringify': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/promises': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-subscriptions-api': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions-channel-websocket': 3.0.3(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-transformers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/subscribable': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/rpc-subscriptions@3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/fast-stable-stringify': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/promises': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-subscriptions-api': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions-channel-websocket': 3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-transformers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/subscribable': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/rpc-subscriptions@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) '@solana/fast-stable-stringify': 5.0.0(typescript@5.8.3) @@ -8917,7 +11928,7 @@ snapshots: '@solana/promises': 5.0.0(typescript@5.8.3) '@solana/rpc-spec-types': 5.0.0(typescript@5.8.3) '@solana/rpc-subscriptions-api': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/rpc-subscriptions-channel-websocket': 5.0.0(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-channel-websocket': 5.0.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/rpc-subscriptions-spec': 5.0.0(typescript@5.8.3) '@solana/rpc-transformers': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -8927,7 +11938,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/rpc-subscriptions@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) '@solana/fast-stable-stringify': 5.0.0(typescript@5.8.3) @@ -8935,7 +11946,7 @@ snapshots: '@solana/promises': 5.0.0(typescript@5.8.3) '@solana/rpc-spec-types': 5.0.0(typescript@5.8.3) '@solana/rpc-subscriptions-api': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/rpc-subscriptions-channel-websocket': 5.0.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-channel-websocket': 5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/rpc-subscriptions-spec': 5.0.0(typescript@5.8.3) '@solana/rpc-transformers': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -8945,6 +11956,28 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/rpc-transformers@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/nominal-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc-transformers@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc-transformers@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) @@ -8956,6 +11989,22 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc-transport-http@2.3.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + undici-types: 7.16.0 + + '@solana/rpc-transport-http@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + undici-types: 7.16.0 + '@solana/rpc-transport-http@5.0.0(typescript@5.8.3)': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) @@ -8964,6 +12013,30 @@ snapshots: typescript: 5.8.3 undici-types: 7.16.0 + '@solana/rpc-types@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-numbers': 2.3.0(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/nominal-types': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc-types@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc-types@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -8976,6 +12049,36 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/fast-stable-stringify': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/rpc-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-spec': 2.3.0(typescript@5.8.3) + '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-transport-http': 2.3.0(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/fast-stable-stringify': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/rpc-api': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-transformers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-transport-http': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) @@ -8991,6 +12094,34 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/signers@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/instructions': 2.3.0(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/nominal-types': 2.3.0(typescript@5.8.3) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/signers@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/instructions': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/signers@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -9005,41 +12136,40 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/spl-token-group@0.0.7(@solana/web3.js@1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + '@solana/subscribable@2.3.0(typescript@5.8.3)': dependencies: - '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - typescript + '@solana/errors': 2.3.0(typescript@5.8.3) + typescript: 5.8.3 - '@solana/spl-token-metadata@0.1.6(@solana/web3.js@1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + '@solana/subscribable@3.0.3(typescript@5.8.3)': dependencies: - '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - typescript + '@solana/errors': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 - '@solana/spl-token@0.4.13(@solana/web3.js@1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)': + '@solana/subscribable@5.0.0(typescript@5.8.3)': dependencies: - '@solana/buffer-layout': 4.0.1 - '@solana/buffer-layout-utils': 0.2.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana/spl-token-group': 0.0.7(@solana/web3.js@1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/spl-token-metadata': 0.1.6(@solana/web3.js@1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) - buffer: 6.0.3 + '@solana/errors': 5.0.0(typescript@5.8.3) + typescript: 5.8.3 + + '@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 transitivePeerDependencies: - - bufferutil - - encoding - fastestsmallesttextencoderdecoder - - typescript - - utf-8-validate - '@solana/subscribable@5.0.0(typescript@5.8.3)': + '@solana/sysvars@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: - '@solana/errors': 5.0.0(typescript@5.8.3) + '@solana/accounts': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder '@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: @@ -9051,7 +12181,92 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transaction-confirmation@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/promises': 2.3.0(typescript@5.8.3) + '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/promises': 2.3.0(typescript@5.8.3) + '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/transaction-confirmation@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/promises': 3.0.3(typescript@5.8.3) + '@solana/rpc': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/transaction-confirmation@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/promises': 3.0.3(typescript@5.8.3) + '@solana/rpc': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/transaction-confirmation@3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/promises': 3.0.3(typescript@5.8.3) + '@solana/rpc': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions': 3.0.3(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/transaction-confirmation@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -9059,7 +12274,7 @@ snapshots: '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/promises': 5.0.0(typescript@5.8.3) '@solana/rpc': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/rpc-subscriptions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -9068,7 +12283,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/transaction-confirmation@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/transaction-confirmation@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -9076,7 +12291,7 @@ snapshots: '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/promises': 5.0.0(typescript@5.8.3) '@solana/rpc': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/rpc-subscriptions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -9085,6 +12300,36 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/transaction-messages@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-data-structures': 2.3.0(typescript@5.8.3) + '@solana/codecs-numbers': 2.3.0(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/instructions': 2.3.0(typescript@5.8.3) + '@solana/nominal-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/transaction-messages@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-data-structures': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/instructions': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/transaction-messages@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -9100,6 +12345,42 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/transactions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 2.3.0(typescript@5.8.3) + '@solana/codecs-data-structures': 2.3.0(typescript@5.8.3) + '@solana/codecs-numbers': 2.3.0(typescript@5.8.3) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 2.3.0(typescript@5.8.3) + '@solana/functional': 2.3.0(typescript@5.8.3) + '@solana/instructions': 2.3.0(typescript@5.8.3) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/nominal-types': 2.3.0(typescript@5.8.3) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/transactions@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-data-structures': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/instructions': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/transactions@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -9123,13 +12404,13 @@ snapshots: '@wallet-standard/base': 1.1.0 '@wallet-standard/features': 1.1.0 - '@solana/web3.js@1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)': + '@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)': dependencies: - '@babel/runtime': 7.27.6 - '@noble/curves': 1.9.2 + '@babel/runtime': 7.28.4 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@solana/buffer-layout': 4.0.1 - '@solana/codecs-numbers': 2.1.1(typescript@5.8.3) + '@solana/codecs-numbers': 2.3.0(typescript@5.8.3) agentkeepalive: 4.6.0 bn.js: 5.2.2 borsh: 0.7.0 @@ -9138,7 +12419,7 @@ snapshots: fast-stable-stringify: 1.0.0 jayson: 4.2.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) node-fetch: 2.7.0 - rpc-websockets: 9.1.1 + rpc-websockets: 9.2.0 superstruct: 2.0.2 transitivePeerDependencies: - bufferutil @@ -9146,54 +12427,54 @@ snapshots: - typescript - utf-8-validate - '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.0)': + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 - '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.28.0)': + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 - '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.28.0)': + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 - '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.28.0)': + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 - '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.28.0)': + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 - '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.28.0)': + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 - '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.28.0)': + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 - '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.28.0)': + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 - '@svgr/babel-preset@8.1.0(@babel/core@7.28.0)': + '@svgr/babel-preset@8.1.0(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.28.0 - '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.28.0) - '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.28.0) - '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.28.0) - '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.28.0) - '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.28.0) - '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.28.0) - '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.28.0) - '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.28.4) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.28.4) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.28.4) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.28.4) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.28.4) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.28.4) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.28.4) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.28.4) '@svgr/core@8.1.0(typescript@5.8.3)': dependencies: - '@babel/core': 7.28.0 - '@svgr/babel-preset': 8.1.0(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@svgr/babel-preset': 8.1.0(@babel/core@7.28.4) camelcase: 6.3.0 cosmiconfig: 8.3.6(typescript@5.8.3) snake-case: 3.0.4 @@ -9203,13 +12484,13 @@ snapshots: '@svgr/hast-util-to-babel-ast@8.0.0': dependencies: - '@babel/types': 7.28.0 + '@babel/types': 7.28.4 entities: 4.5.0 '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.8.3))': dependencies: - '@babel/core': 7.28.0 - '@svgr/babel-preset': 8.1.0(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@svgr/babel-preset': 8.1.0(@babel/core@7.28.4) '@svgr/core': 8.1.0(typescript@5.8.3) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 @@ -9227,11 +12508,11 @@ snapshots: '@svgr/webpack@8.1.0(typescript@5.8.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/plugin-transform-react-constant-elements': 7.27.1(@babel/core@7.28.0) - '@babel/preset-env': 7.28.0(@babel/core@7.28.0) - '@babel/preset-react': 7.27.1(@babel/core@7.28.0) - '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/plugin-transform-react-constant-elements': 7.27.1(@babel/core@7.28.4) + '@babel/preset-env': 7.28.3(@babel/core@7.28.4) + '@babel/preset-react': 7.27.1(@babel/core@7.28.4) + '@babel/preset-typescript': 7.27.1(@babel/core@7.28.4) '@svgr/core': 8.1.0(typescript@5.8.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.8.3)) '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.8.3))(typescript@5.8.3) @@ -9239,8 +12520,6 @@ snapshots: - supports-color - typescript - '@swc/counter@0.1.3': {} - '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -9249,28 +12528,21 @@ snapshots: dependencies: tslib: 2.8.1 - '@tanstack/query-core@5.81.5': {} + '@tanstack/query-core@5.90.8': {} - '@tanstack/react-query@5.81.5(react@19.2.1)': + '@tanstack/react-query@5.90.8(react@19.2.0)': dependencies: - '@tanstack/query-core': 5.81.5 + '@tanstack/query-core': 5.90.8 + react: 19.2.0 + + '@tanstack/react-query@5.90.8(react@19.2.1)': + dependencies: + '@tanstack/query-core': 5.90.8 react: 19.2.1 '@trysound/sax@0.2.0': {} - '@tsconfig/node10@1.0.11': - optional: true - - '@tsconfig/node12@1.0.11': - optional: true - - '@tsconfig/node14@1.0.3': - optional: true - - '@tsconfig/node16@1.0.4': - optional: true - - '@tybys/wasm-util@0.9.0': + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 optional: true @@ -9278,15 +12550,16 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.19.4 + '@types/node': 22.16.0 - '@types/chai@5.2.2': + '@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': 20.19.4 + '@types/node': 22.16.0 '@types/debug@4.1.12': dependencies: @@ -9298,14 +12571,14 @@ snapshots: '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 20.19.4 + '@types/node': 22.16.0 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 - '@types/express-serve-static-core@5.0.6': + '@types/express-serve-static-core@5.1.0': dependencies: - '@types/node': 20.19.4 + '@types/node': 22.16.0 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 @@ -9320,7 +12593,7 @@ snapshots: '@types/express@5.0.3': dependencies: '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 5.0.6 + '@types/express-serve-static-core': 5.1.0 '@types/serve-static': 1.15.8 '@types/http-errors@2.0.5': {} @@ -9329,6 +12602,8 @@ snapshots: '@types/json5@0.0.29': {} + '@types/lodash@4.17.20': {} + '@types/mime@1.3.5': {} '@types/ms@2.1.0': {} @@ -9343,27 +12618,32 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/prompts@2.4.9': + dependencies: + '@types/node': 22.16.0 + kleur: 3.0.3 + '@types/qs@6.14.0': {} '@types/range-parser@1.2.7': {} - '@types/react-dom@19.1.6(@types/react@19.1.8)': + '@types/react-dom@19.2.2(@types/react@19.2.2)': dependencies: - '@types/react': 19.1.8 + '@types/react': 19.2.2 - '@types/react@19.1.8': + '@types/react@19.2.2': dependencies: csstype: 3.1.3 '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.19.4 + '@types/node': 22.16.0 '@types/serve-static@1.15.8': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 20.19.4 + '@types/node': 22.16.0 '@types/send': 0.17.5 '@types/trusted-types@2.0.7': {} @@ -9372,21 +12652,38 @@ snapshots: '@types/ws@7.4.7': dependencies: - '@types/node': 20.19.4 + '@types/node': 22.16.0 '@types/ws@8.18.1': dependencies: - '@types/node': 20.19.4 + '@types/node': 22.16.0 + + '@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.46.2 + '@typescript-eslint/type-utils': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.46.2 + eslint: 9.38.0(jiti@1.21.7) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color - '@typescript-eslint/eslint-plugin@8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.35.1 - '@typescript-eslint/type-utils': 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.35.1 - eslint: 9.30.1(jiti@1.21.7) + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.48.0 + '@typescript-eslint/type-utils': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/utils': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.48.0 + eslint: 9.38.0(jiti@1.21.7) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -9395,192 +12692,506 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.46.2 + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.46.2 + debug: 4.4.3 + eslint: 9.38.0(jiti@1.21.7) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.48.0 + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.48.0 + debug: 4.4.3 + eslint: 9.38.0(jiti@1.21.7) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.46.2(typescript@5.8.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.8.3) + '@typescript-eslint/types': 8.46.2 + debug: 4.4.3 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.48.0(typescript@5.8.3)': dependencies: - '@typescript-eslint/scope-manager': 8.35.1 - '@typescript-eslint/types': 8.35.1 - '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.35.1 - debug: 4.4.1 - eslint: 9.30.1(jiti@1.21.7) + '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.8.3) + '@typescript-eslint/types': 8.48.0 + debug: 4.4.3 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.35.1(typescript@5.8.3)': + '@typescript-eslint/scope-manager@8.46.2': + dependencies: + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/visitor-keys': 8.46.2 + + '@typescript-eslint/scope-manager@8.48.0': + dependencies: + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/visitor-keys': 8.48.0 + + '@typescript-eslint/tsconfig-utils@8.46.2(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@typescript-eslint/tsconfig-utils@8.48.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@typescript-eslint/type-utils@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.8.3) - '@typescript-eslint/types': 8.35.1 - debug: 4.4.1 + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.8.3) + '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + debug: 4.4.3 + eslint: 9.38.0(jiti@1.21.7) + ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.35.1': + '@typescript-eslint/type-utils@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3)': dependencies: - '@typescript-eslint/types': 8.35.1 - '@typescript-eslint/visitor-keys': 8.35.1 + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + debug: 4.4.3 + eslint: 9.38.0(jiti@1.21.7) + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.46.2': {} + + '@typescript-eslint/types@8.48.0': {} - '@typescript-eslint/tsconfig-utils@8.35.1(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.46.2(typescript@5.8.3)': dependencies: + '@typescript-eslint/project-service': 8.46.2(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.8.3) + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/visitor-keys': 8.46.2 + debug: 4.4.3 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 + transitivePeerDependencies: + - supports-color - '@typescript-eslint/type-utils@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.48.0(typescript@5.8.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) - '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - debug: 4.4.1 - eslint: 9.30.1(jiti@1.21.7) + '@typescript-eslint/project-service': 8.48.0(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.8.3) + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/visitor-keys': 8.48.0 + debug: 4.4.3 + minimatch: 9.0.5 + semver: 7.7.3 + tinyglobby: 0.2.15 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.35.1': {} - - '@typescript-eslint/typescript-estree@8.35.1(typescript@5.8.3)': + '@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@1.21.7)) + '@typescript-eslint/scope-manager': 8.46.2 + '@typescript-eslint/types': 8.46.2 + '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.8.3) + eslint: 9.38.0(jiti@1.21.7) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@1.21.7)) + '@typescript-eslint/scope-manager': 8.48.0 + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.8.3) + eslint: 9.38.0(jiti@1.21.7) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.46.2': + dependencies: + '@typescript-eslint/types': 8.46.2 + eslint-visitor-keys: 4.2.1 + + '@typescript-eslint/visitor-keys@8.48.0': + dependencies: + '@typescript-eslint/types': 8.48.0 + eslint-visitor-keys: 4.2.1 + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.19 + optionalDependencies: + vite: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.4': + dependencies: + '@vitest/utils': 3.2.4 + pathe: 2.0.3 + strip-literal: 3.1.0 + + '@vitest/snapshot@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + magic-string: 0.30.19 + pathe: 2.0.3 + + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.4 + + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + + '@wagmi/connectors@5.11.2(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71)': + dependencies: + '@base-org/account': 1.1.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(zod@3.25.71) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(zod@3.25.71) + '@gemini-wallet/core': 0.2.0(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + cbw-sdk: '@coinbase/wallet-sdk@3.9.3' + porto: 0.2.19(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/react-query' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - react + - supports-color + - uploadthing + - use-sync-external-store + - utf-8-validate + - wagmi + - zod + + '@wagmi/connectors@5.11.2(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71)': + dependencies: + '@base-org/account': 1.1.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) + '@gemini-wallet/core': 0.2.0(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + cbw-sdk: '@coinbase/wallet-sdk@3.9.3' + porto: 0.2.19(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) + viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/react-query' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - react + - supports-color + - uploadthing + - use-sync-external-store + - utf-8-validate + - wagmi + - zod + + '@wagmi/connectors@6.1.0(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71)': + dependencies: + '@base-org/account': 1.1.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(zod@3.25.71) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(zod@3.25.71) + '@gemini-wallet/core': 0.2.0(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + cbw-sdk: '@coinbase/wallet-sdk@3.9.3' + porto: 0.2.19(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/react-query' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - react + - supports-color + - uploadthing + - use-sync-external-store + - utf-8-validate + - wagmi + - zod + + '@wagmi/connectors@6.1.0(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71)': dependencies: - '@typescript-eslint/project-service': 8.35.1(typescript@5.8.3) - '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.8.3) - '@typescript-eslint/types': 8.35.1 - '@typescript-eslint/visitor-keys': 8.35.1 - debug: 4.4.1 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.2 - ts-api-utils: 2.1.0(typescript@5.8.3) + '@base-org/account': 1.1.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) + '@gemini-wallet/core': 0.2.0(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + cbw-sdk: '@coinbase/wallet-sdk@3.9.3' + porto: 0.2.19(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) + viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/react-query' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - react - supports-color + - uploadthing + - use-sync-external-store + - utf-8-validate + - wagmi + - zod - '@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3)': + '@wagmi/connectors@6.1.0(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@1.21.7)) - '@typescript-eslint/scope-manager': 8.35.1 - '@typescript-eslint/types': 8.35.1 - '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) - eslint: 9.30.1(jiti@1.21.7) + '@base-org/account': 1.1.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) + '@gemini-wallet/core': 0.2.0(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + cbw-sdk: '@coinbase/wallet-sdk@3.9.3' + porto: 0.2.19(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/react-query' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - react - supports-color + - uploadthing + - use-sync-external-store + - utf-8-validate + - wagmi + - zod - '@typescript-eslint/visitor-keys@8.35.1': - dependencies: - '@typescript-eslint/types': 8.35.1 - eslint-visitor-keys: 4.2.1 - - '@unrs/resolver-binding-android-arm-eabi@1.10.1': - optional: true - - '@unrs/resolver-binding-android-arm64@1.10.1': - optional: true - - '@unrs/resolver-binding-darwin-arm64@1.10.1': - optional: true - - '@unrs/resolver-binding-darwin-x64@1.10.1': - optional: true - - '@unrs/resolver-binding-freebsd-x64@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-arm-gnueabihf@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-arm-musleabihf@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-arm64-gnu@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-arm64-musl@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-ppc64-gnu@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-riscv64-gnu@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-riscv64-musl@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-s390x-gnu@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-x64-gnu@1.10.1': - optional: true - - '@unrs/resolver-binding-linux-x64-musl@1.10.1': - optional: true - - '@unrs/resolver-binding-wasm32-wasi@1.10.1': - dependencies: - '@napi-rs/wasm-runtime': 0.2.11 - optional: true - - '@unrs/resolver-binding-win32-arm64-msvc@1.10.1': - optional: true - - '@unrs/resolver-binding-win32-ia32-msvc@1.10.1': - optional: true - - '@unrs/resolver-binding-win32-x64-msvc@1.10.1': - optional: true - - '@vitest/expect@3.2.4': - dependencies: - '@types/chai': 5.2.2 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.2.0 - tinyrainbow: 2.0.0 - - '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0))': - dependencies: - '@vitest/spy': 3.2.4 - estree-walker: 3.0.3 - magic-string: 0.30.17 - optionalDependencies: - vite: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) - - '@vitest/pretty-format@3.2.4': - dependencies: - tinyrainbow: 2.0.0 - - '@vitest/runner@3.2.4': - dependencies: - '@vitest/utils': 3.2.4 - pathe: 2.0.3 - strip-literal: 3.0.0 - - '@vitest/snapshot@3.2.4': - dependencies: - '@vitest/pretty-format': 3.2.4 - magic-string: 0.30.17 - pathe: 2.0.3 - - '@vitest/spy@3.2.4': - dependencies: - tinyspy: 4.0.3 - - '@vitest/utils@3.2.4': - dependencies: - '@vitest/pretty-format': 3.2.4 - loupe: 3.1.4 - tinyrainbow: 2.0.0 - - '@wagmi/connectors@5.8.5(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)': + '@wagmi/connectors@6.1.0(@tanstack/react-query@5.90.8(react@19.2.1))(@wagmi/core@2.22.1(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71)': dependencies: - '@coinbase/wallet-sdk': 4.3.3 - '@metamask/sdk': 0.32.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@base-org/account': 1.1.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.71) + '@gemini-wallet/core': 0.2.0(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@walletconnect/ethereum-provider': 2.21.1(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + porto: 0.2.19(@tanstack/react-query@5.90.8(react@19.2.1))(@wagmi/core@2.22.1(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: @@ -9595,29 +13206,64 @@ snapshots: - '@netlify/blobs' - '@planetscale/database' - '@react-native-async-storage/async-storage' + - '@tanstack/react-query' - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil - db0 - encoding + - immer - ioredis - react - supports-color - uploadthing + - use-sync-external-store - utf-8-validate + - wagmi - zod - '@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))': + '@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))': + dependencies: + eventemitter3: 5.0.1 + mipd: 0.0.7(typescript@5.8.3) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zustand: 5.0.0(@types/react@19.2.2)(react@19.2.0)(use-sync-external-store@1.4.0(react@19.2.0)) + optionalDependencies: + '@tanstack/query-core': 5.90.8 + typescript: 5.8.3 + transitivePeerDependencies: + - '@types/react' + - immer + - react + - use-sync-external-store + + '@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))': dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@5.8.3) viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - zustand: 5.0.0(@types/react@19.1.8)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + zustand: 5.0.0(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + optionalDependencies: + '@tanstack/query-core': 5.90.8 + typescript: 5.8.3 + transitivePeerDependencies: + - '@types/react' + - immer + - react + - use-sync-external-store + + '@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))': + dependencies: + eventemitter3: 5.0.1 + mipd: 0.0.7(typescript@5.8.3) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zustand: 5.0.0(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) optionalDependencies: - '@tanstack/query-core': 5.81.5 + '@tanstack/query-core': 5.90.8 typescript: 5.8.3 transitivePeerDependencies: - '@types/react' @@ -9668,6 +13314,7 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -9696,7 +13343,90 @@ snapshots: '@walletconnect/window-getters': 1.0.1 es-toolkit: 1.33.0 events: 3.3.0 - uint8arrays: 3.1.0 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + + '@walletconnect/environment@1.0.1': + dependencies: + tslib: 1.14.1 + + '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + dependencies: + '@reown/appkit': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@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.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@walletconnect/types': 2.21.1 + '@walletconnect/universal-provider': 2.21.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - zod + + '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + dependencies: + '@reown/appkit': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@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.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@walletconnect/types': 2.21.1 + '@walletconnect/universal-provider': 2.21.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -9709,25 +13439,25 @@ snapshots: - '@netlify/blobs' - '@planetscale/database' - '@react-native-async-storage/async-storage' + - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil - db0 + - encoding - ioredis + - react - typescript - uploadthing - utf-8-validate - zod - '@walletconnect/environment@1.0.1': - dependencies: - tslib: 1.14.1 - - '@walletconnect/ethereum-provider@2.21.1(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + '@walletconnect/ethereum-provider@2.21.1(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': dependencies: - '@reown/appkit': 1.7.8(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + '@reown/appkit': 1.7.8(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) '@walletconnect/jsonrpc-http-connection': 1.0.8 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 @@ -9753,6 +13483,7 @@ snapshots: - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -9816,7 +13547,7 @@ snapshots: dependencies: '@walletconnect/safe-json': 1.0.2 idb-keyval: 6.2.2 - unstorage: 1.16.0(idb-keyval@6.2.2) + unstorage: 1.17.1(idb-keyval@6.2.2) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -9830,6 +13561,7 @@ snapshots: - '@planetscale/database' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - db0 @@ -9882,6 +13614,7 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -9917,6 +13650,7 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -9953,6 +13687,7 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - db0 @@ -9981,6 +13716,7 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - db0 @@ -10015,6 +13751,7 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -10054,6 +13791,7 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -10098,6 +13836,7 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -10141,6 +13880,7 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -10165,16 +13905,41 @@ snapshots: typescript: 5.8.3 zod: 3.25.71 - abitype@1.0.8(typescript@5.8.3)(zod@3.22.4): + abitype@1.0.8(typescript@5.8.3)(zod@3.25.71): + optionalDependencies: + typescript: 5.8.3 + zod: 3.25.71 + + abitype@1.1.0(typescript@5.8.3)(zod@3.22.4): optionalDependencies: typescript: 5.8.3 zod: 3.22.4 - abitype@1.0.8(typescript@5.8.3)(zod@3.25.71): + abitype@1.1.0(typescript@5.8.3)(zod@3.25.71): + optionalDependencies: + typescript: 5.8.3 + zod: 3.25.71 + + abitype@1.1.0(typescript@5.8.3)(zod@4.1.12): + optionalDependencies: + typescript: 5.8.3 + zod: 4.1.12 + + abitype@1.1.1(typescript@5.8.3)(zod@3.22.4): + optionalDependencies: + typescript: 5.8.3 + zod: 3.22.4 + + abitype@1.1.1(typescript@5.8.3)(zod@3.25.71): optionalDependencies: typescript: 5.8.3 zod: 3.25.71 + abitype@1.1.1(typescript@5.8.3)(zod@4.1.12): + optionalDependencies: + typescript: 5.8.3 + zod: 4.1.12 + accepts@1.3.8: dependencies: mime-types: 2.1.35 @@ -10184,14 +13949,9 @@ snapshots: dependencies: acorn: 8.15.0 - acorn-walk@8.3.4: - dependencies: - acorn: 8.15.0 - optional: true - acorn@8.15.0: {} - agent-base@7.1.3: {} + agent-base@7.1.4: {} agentkeepalive@4.6.0: dependencies: @@ -10204,15 +13964,22 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-regex@5.0.1: {} - ansi-regex@6.1.0: {} + ansi-regex@6.2.2: {} ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.1: {} + ansi-styles@6.2.3: {} any-promise@1.3.0: {} @@ -10223,9 +13990,6 @@ snapshots: are-docs-informative@0.0.2: {} - arg@4.1.3: - optional: true - arg@5.0.2: {} argparse@2.0.1: {} @@ -10327,11 +14091,11 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - axe-core@4.10.3: {} + axe-core@4.11.0: {} - axios-retry@4.5.0(axios@1.10.0): + axios-retry@4.5.0(axios@1.12.2): dependencies: - axios: 1.10.0 + axios: 1.12.2 is-retry-allowed: 2.2.0 axios@1.10.0: @@ -10342,29 +14106,37 @@ snapshots: transitivePeerDependencies: - debug + axios@1.12.2: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + axobject-query@4.1.0: {} - babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.0): + babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.4): dependencies: - '@babel/compat-data': 7.28.0 - '@babel/core': 7.28.0 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0) + '@babel/compat-data': 7.28.4 + '@babel/core': 7.28.4 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.4) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.0): + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.4): dependencies: - '@babel/core': 7.28.0 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0) - core-js-compat: 3.43.0 + '@babel/core': 7.28.4 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.4) + core-js-compat: 3.46.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.0): + babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.4): dependencies: - '@babel/core': 7.28.0 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0) + '@babel/core': 7.28.4 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.4) transitivePeerDependencies: - supports-color @@ -10378,20 +14150,12 @@ snapshots: base64-js@1.5.1: {} - big.js@6.2.2: {} - - bigint-buffer@1.1.5: - dependencies: - bindings: 1.5.0 + baseline-browser-mapping@2.8.19: {} - bignumber.js@9.3.0: {} + big.js@6.2.2: {} binary-extensions@2.3.0: {} - bindings@1.5.0: - dependencies: - file-uri-to-path: 1.0.0 - bn.js@4.12.2: {} bn.js@5.2.2: {} @@ -10421,7 +14185,7 @@ snapshots: bs58: 4.0.1 text-encoding-utf-8: 1.0.2 - bowser@2.11.0: {} + bowser@2.12.1: {} brace-expansion@1.1.12: dependencies: @@ -10441,7 +14205,7 @@ snapshots: browserify-aes@1.2.0: dependencies: buffer-xor: 1.0.3 - cipher-base: 1.0.6 + cipher-base: 1.0.7 create-hash: 1.2.0 evp_bytestokey: 1.0.3 inherits: 2.0.4 @@ -10455,7 +14219,7 @@ snapshots: browserify-des@1.0.2: dependencies: - cipher-base: 1.0.6 + cipher-base: 1.0.7 des.js: 1.1.0 inherits: 2.0.4 safe-buffer: 5.2.1 @@ -10466,25 +14230,25 @@ snapshots: randombytes: 2.1.0 safe-buffer: 5.2.1 - browserify-sign@4.2.3: + browserify-sign@4.2.5: dependencies: bn.js: 5.2.2 browserify-rsa: 4.1.1 create-hash: 1.2.0 create-hmac: 1.1.7 elliptic: 6.6.1 - hash-base: 3.0.5 inherits: 2.0.4 - parse-asn1: 5.1.7 + parse-asn1: 5.1.9 readable-stream: 2.3.8 safe-buffer: 5.2.1 - browserslist@4.25.1: + browserslist@4.27.0: dependencies: - caniuse-lite: 1.0.30001726 - electron-to-chromium: 1.5.179 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.25.1) + baseline-browser-mapping: 2.8.19 + caniuse-lite: 1.0.30001751 + electron-to-chromium: 1.5.239 + node-releases: 2.0.26 + update-browserslist-db: 1.1.4(browserslist@4.27.0) bs58@4.0.1: dependencies: @@ -10515,10 +14279,6 @@ snapshots: esbuild: 0.25.5 load-tsconfig: 0.2.5 - busboy@1.6.0: - dependencies: - streamsearch: 1.1.0 - bytes@3.1.2: {} cac@6.7.14: {} @@ -10548,14 +14308,14 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001726: {} + caniuse-lite@1.0.30001751: {} - chai@5.2.0: + chai@5.3.3: dependencies: assertion-error: 2.0.1 check-error: 2.1.1 deep-eql: 5.0.2 - loupe: 3.1.4 + loupe: 3.2.1 pathval: 2.0.1 chalk@4.1.2: @@ -10563,8 +14323,6 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.4.1: {} - chalk@5.6.2: {} charenc@0.0.2: {} @@ -10587,10 +14345,11 @@ snapshots: dependencies: readdirp: 4.1.2 - cipher-base@1.0.6: + cipher-base@1.0.7: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 + to-buffer: 1.2.2 client-only@0.0.1: {} @@ -10610,27 +14369,13 @@ snapshots: color-name@1.1.4: {} - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - optional: true - - color@4.2.3: - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - optional: true - combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 comlink@4.4.2: {} - commander@12.1.0: {} - - commander@13.1.0: {} + commander@14.0.0: {} commander@14.0.1: {} @@ -10662,9 +14407,9 @@ snapshots: cookie@0.7.1: {} - core-js-compat@3.43.0: + core-js-compat@3.46.0: dependencies: - browserslist: 4.25.1 + browserslist: 4.27.0 core-util-is@1.0.3: {} @@ -10684,33 +14429,23 @@ snapshots: bn.js: 4.12.2 elliptic: 6.6.1 - create-hash@1.1.3: - dependencies: - cipher-base: 1.0.6 - inherits: 2.0.4 - ripemd160: 2.0.1 - sha.js: 2.4.12 - create-hash@1.2.0: dependencies: - cipher-base: 1.0.6 + cipher-base: 1.0.7 inherits: 2.0.4 md5.js: 1.3.5 - ripemd160: 2.0.2 + ripemd160: 2.0.3 sha.js: 2.4.12 create-hmac@1.1.7: dependencies: - cipher-base: 1.0.6 + cipher-base: 1.0.7 create-hash: 1.2.0 inherits: 2.0.4 - ripemd160: 2.0.2 + ripemd160: 2.0.3 safe-buffer: 5.2.1 sha.js: 2.4.12 - create-require@1.1.1: - optional: true - cross-fetch@3.2.0: dependencies: node-fetch: 2.7.0 @@ -10738,14 +14473,14 @@ snapshots: crypto-browserify@3.12.1: dependencies: browserify-cipher: 1.0.1 - browserify-sign: 4.2.3 + browserify-sign: 4.2.5 create-ecdh: 4.0.4 create-hash: 1.2.0 create-hmac: 1.1.7 diffie-hellman: 5.0.3 hash-base: 3.0.5 inherits: 2.0.4 - pbkdf2: 3.1.3 + pbkdf2: 3.1.5 public-encrypt: 4.0.3 randombytes: 2.1.0 randomfill: 1.0.4 @@ -10810,7 +14545,7 @@ snapshots: date-fns@2.30.0: dependencies: - '@babel/runtime': 7.27.6 + '@babel/runtime': 7.28.4 dayjs@1.11.13: {} @@ -10822,17 +14557,17 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.3.7: + debug@4.3.4: dependencies: - ms: 2.1.3 + ms: 2.1.2 - debug@4.4.1: + debug@4.4.3: dependencies: ms: 2.1.3 decamelize@1.2.0: {} - decimal.js@10.5.0: {} + decimal.js@10.6.0: {} decode-uri-component@0.2.2: {} @@ -10862,9 +14597,17 @@ snapshots: depd@2.0.0: {} - derive-valtio@0.1.0(valtio@1.13.2(@types/react@19.1.8)(react@19.2.1)): + derive-valtio@0.1.0(valtio@1.13.2(@types/react@19.2.2)(react@19.2.0)): + dependencies: + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.0) + + derive-valtio@0.1.0(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1)): dependencies: - valtio: 1.13.2(@types/react@19.1.8)(react@19.2.1) + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) + + derive-valtio@0.1.0(valtio@1.13.2(react@19.2.1)): + dependencies: + valtio: 1.13.2(react@19.2.1) des.js@1.1.0: dependencies: @@ -10877,14 +14620,11 @@ snapshots: detect-browser@5.3.0: {} - detect-libc@2.0.4: + detect-libc@2.1.2: optional: true didyoumean@1.2.2: {} - diff@4.0.2: - optional: true - diffie-hellman@5.0.3: dependencies: bn.js: 4.12.2 @@ -10945,16 +14685,16 @@ snapshots: eastasianwidth@0.2.0: {} - eciesjs@0.4.15: + eciesjs@0.4.16: dependencies: - '@ecies/ciphers': 0.2.3(@noble/ciphers@1.3.0) + '@ecies/ciphers': 0.2.4(@noble/ciphers@1.3.0) '@noble/ciphers': 1.3.0 - '@noble/curves': 1.9.2 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 ee-first@1.1.1: {} - electron-to-chromium@1.5.179: {} + electron-to-chromium@1.5.239: {} elliptic@6.6.1: dependencies: @@ -10983,7 +14723,7 @@ snapshots: engine.io-client@6.6.3(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 + debug: 4.3.4 engine.io-parser: 5.2.3 ws: 8.17.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) xmlhttprequest-ssl: 2.1.2 @@ -10998,7 +14738,7 @@ snapshots: entities@6.0.1: {} - error-ex@1.3.2: + error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 @@ -11173,22 +14913,42 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-next@15.1.7(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3): + eslint-config-next@15.1.9(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3): + dependencies: + '@next/eslint-plugin-next': 15.1.9 + '@rushstack/eslint-patch': 1.14.0 + '@typescript-eslint/eslint-plugin': 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: 9.38.0(jiti@1.21.7) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-react: 7.37.5(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-react-hooks: 5.2.0(eslint@9.38.0(jiti@1.21.7)) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - supports-color + + eslint-config-next@16.0.7(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3): dependencies: - '@next/eslint-plugin-next': 15.1.7 - '@rushstack/eslint-patch': 1.12.0 - '@typescript-eslint/eslint-plugin': 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - eslint: 9.30.1(jiti@1.21.7) + '@next/eslint-plugin-next': 16.0.7 + eslint: 9.38.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@1.21.7)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.30.1(jiti@1.21.7)) - eslint-plugin-react: 7.37.5(eslint@9.30.1(jiti@1.21.7)) - eslint-plugin-react-hooks: 5.2.0(eslint@9.30.1(jiti@1.21.7)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-react: 7.37.5(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-react-hooks: 7.0.1(eslint@9.38.0(jiti@1.21.7)) + globals: 16.4.0 + typescript-eslint: 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: + - '@typescript-eslint/parser' - eslint-import-resolver-webpack - eslint-plugin-import-x - supports-color @@ -11197,37 +14957,77 @@ snapshots: dependencies: debug: 3.2.7 is-core-module: 2.16.1 - resolve: 1.22.10 + resolve: 1.22.11 transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@1.21.7)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@1.21.7)): dependencies: '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.1 - eslint: 9.30.1(jiti@1.21.7) + debug: 4.4.3 + eslint: 9.38.0(jiti@1.21.7) get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 - tinyglobby: 0.2.14 - unrs-resolver: 1.10.1 + tinyglobby: 0.2.15 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)): + dependencies: + debug: 3.2.7 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: 9.38.0(jiti@1.21.7) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@1.21.7)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) - eslint: 9.30.1(jiti@1.21.7) + '@typescript-eslint/parser': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: 9.38.0(jiti@1.21.7) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.38.0(jiti@1.21.7)) + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.38.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@1.21.7)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -11236,9 +15036,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.30.1(jiti@1.21.7) + eslint: 9.38.0(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@1.21.7)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.38.0(jiti@1.21.7)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -11250,39 +15050,39 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsdoc@50.8.0(eslint@9.30.1(jiti@1.21.7)): + eslint-plugin-jsdoc@50.8.0(eslint@9.38.0(jiti@1.21.7)): dependencies: '@es-joy/jsdoccomment': 0.50.2 are-docs-informative: 0.0.2 comment-parser: 1.4.1 - debug: 4.4.1 + debug: 4.4.3 escape-string-regexp: 4.0.0 - eslint: 9.30.1(jiti@1.21.7) + eslint: 9.38.0(jiti@1.21.7) espree: 10.4.0 esquery: 1.6.0 parse-imports-exports: 0.2.4 - semver: 7.7.2 + semver: 7.7.3 spdx-expression-parse: 4.0.0 transitivePeerDependencies: - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.30.1(jiti@1.21.7)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.38.0(jiti@1.21.7)): dependencies: aria-query: 5.3.2 array-includes: 3.1.9 array.prototype.flatmap: 1.3.3 ast-types-flow: 0.0.8 - axe-core: 4.10.3 + axe-core: 4.11.0 axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.30.1(jiti@1.21.7) + eslint: 9.38.0(jiti@1.21.7) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -11291,18 +15091,29 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-prettier@5.5.1(eslint@9.30.1(jiti@1.21.7))(prettier@3.5.2): + eslint-plugin-prettier@5.5.4(eslint@9.38.0(jiti@1.21.7))(prettier@3.5.2): dependencies: - eslint: 9.30.1(jiti@1.21.7) + eslint: 9.38.0(jiti@1.21.7) prettier: 3.5.2 prettier-linter-helpers: 1.0.0 - synckit: 0.11.8 + synckit: 0.11.11 + + eslint-plugin-react-hooks@5.2.0(eslint@9.38.0(jiti@1.21.7)): + dependencies: + eslint: 9.38.0(jiti@1.21.7) - eslint-plugin-react-hooks@5.2.0(eslint@9.30.1(jiti@1.21.7)): + eslint-plugin-react-hooks@7.0.1(eslint@9.38.0(jiti@1.21.7)): dependencies: - eslint: 9.30.1(jiti@1.21.7) + '@babel/core': 7.28.4 + '@babel/parser': 7.28.4 + eslint: 9.38.0(jiti@1.21.7) + hermes-parser: 0.25.1 + zod: 3.25.71 + zod-validation-error: 4.0.2(zod@3.25.71) + transitivePeerDependencies: + - supports-color - eslint-plugin-react@7.37.5(eslint@9.30.1(jiti@1.21.7)): + eslint-plugin-react@7.37.5(eslint@9.38.0(jiti@1.21.7)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -11310,7 +15121,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.30.1(jiti@1.21.7) + eslint: 9.38.0(jiti@1.21.7) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -11333,25 +15144,24 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.30.1(jiti@1.21.7): + eslint@9.38.0(jiti@1.21.7): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@1.21.7)) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.21.0 - '@eslint/config-helpers': 0.3.0 - '@eslint/core': 0.14.0 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@1.21.7)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.1 + '@eslint/core': 0.16.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.30.1 - '@eslint/plugin-kit': 0.3.3 - '@humanfs/node': 0.16.6 + '@eslint/js': 9.38.0 + '@eslint/plugin-kit': 0.4.0 + '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.1 + debug: 4.4.3 escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -11456,7 +15266,7 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 - expect-type@1.2.1: {} + expect-type@1.2.2: {} express@4.21.2: dependencies: @@ -11531,22 +15341,22 @@ snapshots: fast-stable-stringify@1.0.0: {} + fast-uri@3.1.0: {} + fastestsmallesttextencoderdecoder@1.0.22: {} fastq@1.19.1: dependencies: reusify: 1.1.0 - fdir@6.4.6(picomatch@4.0.2): + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: - picomatch: 4.0.2 + picomatch: 4.0.3 file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 - file-uri-to-path@1.0.0: {} - fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -11577,9 +15387,9 @@ snapshots: fix-dts-default-cjs-exports@1.0.1: dependencies: - magic-string: 0.30.17 - mlly: 1.7.4 - rollup: 4.44.1 + magic-string: 0.30.19 + mlly: 1.8.0 + rollup: 4.52.5 flat-cache@4.0.1: dependencies: @@ -11607,6 +15417,14 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + form-data@4.0.4: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + forwarded@0.2.0: {} fresh@0.5.2: {} @@ -11627,6 +15445,8 @@ snapshots: functions-have-names@1.2.3: {} + generator-function@2.0.1: {} + gensync@1.0.0-beta.2: {} get-caller-file@2.0.5: {} @@ -11680,6 +15500,8 @@ snapshots: globals@14.0.0: {} + globals@16.4.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -11710,14 +15532,14 @@ snapshots: graphql@16.11.0: {} - h3@1.15.3: + h3@1.15.4: dependencies: cookie-es: 1.2.2 crossws: 0.3.5 defu: 6.1.4 destr: 2.0.5 iron-webcrypto: 1.2.1 - node-mock-http: 1.0.1 + node-mock-http: 1.0.3 radix3: 1.1.2 ufo: 1.6.1 uncrypto: 0.1.3 @@ -11740,14 +15562,17 @@ snapshots: dependencies: has-symbols: 1.1.0 - hash-base@2.0.2: + hash-base@3.0.5: dependencies: inherits: 2.0.4 + safe-buffer: 5.2.1 - hash-base@3.0.5: + hash-base@3.1.2: dependencies: inherits: 2.0.4 + readable-stream: 2.3.8 safe-buffer: 5.2.1 + to-buffer: 1.2.2 hash.js@1.1.7: dependencies: @@ -11758,13 +15583,19 @@ snapshots: dependencies: function-bind: 1.1.2 + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + hmac-drbg@1.0.1: dependencies: hash.js: 1.1.7 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - hono@4.8.3: {} + hono@4.10.2: {} html-encoding-sniffer@4.0.0: dependencies: @@ -11780,15 +15611,15 @@ snapshots: http-proxy-agent@7.0.2: dependencies: - agent-base: 7.1.3 - debug: 4.4.1 + agent-base: 7.1.4 + debug: 4.4.3 transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: - agent-base: 7.1.3 - debug: 4.4.1 + agent-base: 7.1.4 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -11806,6 +15637,8 @@ snapshots: dependencies: safer-buffer: 2.1.2 + idb-keyval@6.2.1: {} + idb-keyval@6.2.2: {} ieee754@1.2.1: {} @@ -11846,9 +15679,6 @@ snapshots: is-arrayish@0.2.1: {} - is-arrayish@0.3.2: - optional: true - is-async-function@2.1.1: dependencies: async-function: 1.0.0 @@ -11874,7 +15704,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 is-callable@1.2.7: {} @@ -11901,9 +15731,10 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-generator-function@1.1.0: + is-generator-function@1.1.2: dependencies: call-bound: 1.0.4 + generator-function: 2.0.1 get-proto: 1.0.1 has-tostringtag: 1.0.2 safe-regex-test: 1.1.0 @@ -11986,6 +15817,10 @@ snapshots: dependencies: ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + isows@1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)): + dependencies: + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + iterator.prototype@1.1.5: dependencies: define-data-property: 1.1.4 @@ -12023,7 +15858,7 @@ snapshots: jose@5.10.0: {} - jose@6.0.11: {} + jose@6.1.0: {} joycon@3.1.1: {} @@ -12041,12 +15876,12 @@ snapshots: dependencies: cssstyle: 4.6.0 data-urls: 5.0.0 - decimal.js: 10.5.0 + decimal.js: 10.6.0 html-encoding-sniffer: 4.0.0 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.20 + nwsapi: 2.2.22 parse5: 7.3.0 rrweb-cssom: 0.8.0 saxes: 6.0.0 @@ -12064,8 +15899,6 @@ snapshots: - supports-color - utf-8-validate - jsesc@3.0.2: {} - jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -12081,6 +15914,8 @@ snapshots: json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json-stringify-safe@5.0.1: {} @@ -12110,6 +15945,8 @@ snapshots: keyvaluestorage-interface@1.0.0: {} + kleur@3.0.3: {} + language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -12125,21 +15962,21 @@ snapshots: lines-and-columns@1.2.4: {} - lit-element@4.2.0: + lit-element@4.2.1: dependencies: - '@lit-labs/ssr-dom-shim': 1.3.0 - '@lit/reactive-element': 2.1.0 - lit-html: 3.3.0 + '@lit-labs/ssr-dom-shim': 1.4.0 + '@lit/reactive-element': 2.1.1 + lit-html: 3.3.1 - lit-html@3.3.0: + lit-html@3.3.1: dependencies: '@types/trusted-types': 2.0.7 lit@3.3.0: dependencies: - '@lit/reactive-element': 2.1.0 - lit-element: 4.2.0 - lit-html: 3.3.0 + '@lit/reactive-element': 2.1.1 + lit-element: 4.2.1 + lit-html: 3.3.1 load-tsconfig@0.2.5: {} @@ -12163,7 +16000,7 @@ snapshots: dependencies: js-tokens: 4.0.0 - loupe@3.1.4: {} + loupe@3.2.1: {} lower-case@2.0.2: dependencies: @@ -12175,12 +16012,9 @@ snapshots: dependencies: yallist: 3.1.1 - magic-string@0.30.17: + magic-string@0.30.19: dependencies: - '@jridgewell/sourcemap-codec': 1.5.4 - - make-error@1.3.6: - optional: true + '@jridgewell/sourcemap-codec': 1.5.5 math-intrinsics@1.1.0: {} @@ -12252,7 +16086,7 @@ snapshots: optionalDependencies: typescript: 5.8.3 - mlly@1.7.4: + mlly@1.8.0: dependencies: acorn: 8.15.0 pathe: 2.0.3 @@ -12261,6 +16095,8 @@ snapshots: ms@2.0.0: {} + ms@2.1.2: {} + ms@2.1.3: {} multiformats@9.9.0: {} @@ -12273,56 +16109,54 @@ snapshots: nanoid@3.3.11: {} - napi-postinstall@0.3.0: {} + napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} negotiator@0.6.3: {} - next@15.3.4(react-dom@19.2.1(react@19.2.1))(react@19.2.1): + next@15.5.7(@babel/core@7.28.4)(react-dom@19.2.1(react@19.2.1))(react@19.2.1): dependencies: - '@next/env': 15.3.4 - '@swc/counter': 0.1.3 + '@next/env': 15.5.7 '@swc/helpers': 0.5.15 - busboy: 1.6.0 - caniuse-lite: 1.0.30001726 + caniuse-lite: 1.0.30001751 postcss: 8.4.31 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - styled-jsx: 5.1.6(@babel/core@7.28.0)(react@19.2.1) + styled-jsx: 5.1.6(@babel/core@7.28.4)(react@19.2.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.3.4 - '@next/swc-darwin-x64': 15.3.4 - '@next/swc-linux-arm64-gnu': 15.3.4 - '@next/swc-linux-arm64-musl': 15.3.4 - '@next/swc-linux-x64-gnu': 15.3.4 - '@next/swc-linux-x64-musl': 15.3.4 - '@next/swc-win32-arm64-msvc': 15.3.4 - '@next/swc-win32-x64-msvc': 15.3.4 - sharp: 0.34.2 + '@next/swc-darwin-arm64': 15.5.7 + '@next/swc-darwin-x64': 15.5.7 + '@next/swc-linux-arm64-gnu': 15.5.7 + '@next/swc-linux-arm64-musl': 15.5.7 + '@next/swc-linux-x64-gnu': 15.5.7 + '@next/swc-linux-x64-musl': 15.5.7 + '@next/swc-win32-arm64-msvc': 15.5.7 + '@next/swc-win32-x64-msvc': 15.5.7 + sharp: 0.34.4 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@15.4.0-canary.113(@babel/core@7.28.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1): + next@16.0.7(react-dom@19.2.1(react@19.2.1))(react@19.2.1): dependencies: - '@next/env': 15.4.0-canary.113 + '@next/env': 16.0.7 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001726 + caniuse-lite: 1.0.30001751 postcss: 8.4.31 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - styled-jsx: 5.1.6(@babel/core@7.28.0)(react@19.2.1) + styled-jsx: 5.1.6(@babel/core@7.28.4)(react@19.2.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.4.0-canary.113 - '@next/swc-darwin-x64': 15.4.0-canary.113 - '@next/swc-linux-arm64-gnu': 15.4.0-canary.113 - '@next/swc-linux-arm64-musl': 15.4.0-canary.113 - '@next/swc-linux-x64-gnu': 15.4.0-canary.113 - '@next/swc-linux-x64-musl': 15.4.0-canary.113 - '@next/swc-win32-arm64-msvc': 15.4.0-canary.113 - '@next/swc-win32-x64-msvc': 15.4.0-canary.113 - sharp: 0.34.2 + '@next/swc-darwin-arm64': 16.0.7 + '@next/swc-darwin-x64': 16.0.7 + '@next/swc-linux-arm64-gnu': 16.0.7 + '@next/swc-linux-arm64-musl': 16.0.7 + '@next/swc-linux-x64-gnu': 16.0.7 + '@next/swc-linux-x64-musl': 16.0.7 + '@next/swc-win32-arm64-msvc': 16.0.7 + '@next/swc-win32-x64-msvc': 16.0.7 + sharp: 0.34.4 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -12334,7 +16168,7 @@ snapshots: node-addon-api@2.0.2: {} - node-fetch-native@1.6.6: {} + node-fetch-native@1.6.7: {} node-fetch@2.7.0: dependencies: @@ -12342,9 +16176,9 @@ snapshots: node-gyp-build@4.8.4: {} - node-mock-http@1.0.1: {} + node-mock-http@1.0.3: {} - node-releases@2.0.19: {} + node-releases@2.0.26: {} normalize-path@3.0.0: {} @@ -12356,7 +16190,7 @@ snapshots: dependencies: boolbase: 1.0.0 - nwsapi@2.2.20: {} + nwsapi@2.2.22: {} obj-multiplex@1.0.0: dependencies: @@ -12411,7 +16245,7 @@ snapshots: ofetch@1.4.1: dependencies: destr: 2.0.5 - node-fetch-native: 1.6.6 + node-fetch-native: 1.6.7 ufo: 1.6.1 on-exit-leak-free@0.2.0: {} @@ -12428,6 +16262,12 @@ snapshots: dependencies: mimic-fn: 2.1.0 + openapi-fetch@0.13.8: + dependencies: + openapi-typescript-helpers: 0.0.15 + + openapi-typescript-helpers@0.0.15: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -12446,11 +16286,11 @@ snapshots: ox@0.4.4(typescript@5.8.3)(zod@3.25.71): dependencies: '@adraffy/ens-normalize': 1.11.0 - '@noble/curves': 1.9.2 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.0.8(typescript@5.8.3)(zod@3.25.71) + abitype: 1.1.1(typescript@5.8.3)(zod@3.25.71) eventemitter3: 5.0.1 optionalDependencies: typescript: 5.8.3 @@ -12460,26 +16300,25 @@ snapshots: ox@0.6.7(typescript@5.8.3)(zod@3.25.71): dependencies: '@adraffy/ens-normalize': 1.11.0 - '@noble/curves': 1.9.2 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.0.8(typescript@5.8.3)(zod@3.25.71) + abitype: 1.1.1(typescript@5.8.3)(zod@3.25.71) eventemitter3: 5.0.1 optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: - zod - ox@0.8.1(typescript@5.8.3)(zod@3.22.4): + ox@0.6.9(typescript@5.8.3)(zod@3.25.71): dependencies: '@adraffy/ens-normalize': 1.11.0 - '@noble/ciphers': 1.3.0 - '@noble/curves': 1.9.2 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.0.8(typescript@5.8.3)(zod@3.22.4) + abitype: 1.1.1(typescript@5.8.3)(zod@3.25.71) eventemitter3: 5.0.1 optionalDependencies: typescript: 5.8.3 @@ -12490,11 +16329,71 @@ snapshots: dependencies: '@adraffy/ens-normalize': 1.11.0 '@noble/ciphers': 1.3.0 - '@noble/curves': 1.9.2 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.0.8(typescript@5.8.3)(zod@3.25.71) + abitype: 1.1.1(typescript@5.8.3)(zod@3.25.71) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - zod + + ox@0.9.12(typescript@5.8.3)(zod@4.1.12): + dependencies: + '@adraffy/ens-normalize': 1.11.0 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.1.1(typescript@5.8.3)(zod@4.1.12) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - zod + + ox@0.9.6(typescript@5.8.3)(zod@3.22.4): + dependencies: + '@adraffy/ens-normalize': 1.11.0 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.1.1(typescript@5.8.3)(zod@3.22.4) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - zod + + ox@0.9.6(typescript@5.8.3)(zod@3.25.71): + dependencies: + '@adraffy/ens-normalize': 1.11.0 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.1.1(typescript@5.8.3)(zod@3.25.71) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - zod + + ox@0.9.6(typescript@5.8.3)(zod@4.1.12): + dependencies: + '@adraffy/ens-normalize': 1.11.0 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.1.1(typescript@5.8.3)(zod@4.1.12) eventemitter3: 5.0.1 optionalDependencies: typescript: 5.8.3 @@ -12525,13 +16424,12 @@ snapshots: dependencies: callsites: 3.1.0 - parse-asn1@5.1.7: + parse-asn1@5.1.9: dependencies: asn1.js: 4.10.1 browserify-aes: 1.2.0 evp_bytestokey: 1.0.3 - hash-base: 3.0.5 - pbkdf2: 3.1.3 + pbkdf2: 3.1.5 safe-buffer: 5.2.1 parse-imports-exports@0.2.4: @@ -12541,7 +16439,7 @@ snapshots: parse-json@5.2.0: dependencies: '@babel/code-frame': 7.27.1 - error-ex: 1.3.2 + error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -12572,20 +16470,20 @@ snapshots: pathval@2.0.1: {} - pbkdf2@3.1.3: + pbkdf2@3.1.5: dependencies: - create-hash: 1.1.3 + create-hash: 1.2.0 create-hmac: 1.1.7 - ripemd160: 2.0.1 + ripemd160: 2.0.3 safe-buffer: 5.2.1 sha.js: 2.4.12 - to-buffer: 1.2.1 + to-buffer: 1.2.2 picocolors@1.1.1: {} picomatch@2.3.1: {} - picomatch@4.0.2: {} + picomatch@4.0.3: {} pify@2.3.0: {} @@ -12619,13 +16517,93 @@ snapshots: pkg-types@1.3.1: dependencies: confbox: 0.1.8 - mlly: 1.7.4 + mlly: 1.8.0 pathe: 2.0.3 pngjs@5.0.0: {} pony-cause@2.1.11: {} + porto@0.2.19(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)): + dependencies: + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + hono: 4.10.2 + idb-keyval: 6.2.2 + mipd: 0.0.7(typescript@5.8.3) + ox: 0.9.12(typescript@5.8.3)(zod@4.1.12) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zod: 4.1.12 + zustand: 5.0.8(@types/react@19.2.2)(react@19.2.0)(use-sync-external-store@1.4.0(react@19.2.0)) + optionalDependencies: + '@tanstack/react-query': 5.90.8(react@19.2.0) + react: 19.2.0 + typescript: 5.8.3 + wagmi: 2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) + transitivePeerDependencies: + - '@types/react' + - immer + - use-sync-external-store + + porto@0.2.19(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)): + dependencies: + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + hono: 4.10.2 + idb-keyval: 6.2.2 + mipd: 0.0.7(typescript@5.8.3) + ox: 0.9.12(typescript@5.8.3)(zod@4.1.12) + viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zod: 4.1.12 + zustand: 5.0.8(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + optionalDependencies: + '@tanstack/react-query': 5.90.8(react@19.2.1) + react: 19.2.1 + typescript: 5.8.3 + wagmi: 2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) + transitivePeerDependencies: + - '@types/react' + - immer + - use-sync-external-store + + porto@0.2.19(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)): + dependencies: + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + hono: 4.10.2 + idb-keyval: 6.2.2 + mipd: 0.0.7(typescript@5.8.3) + ox: 0.9.12(typescript@5.8.3)(zod@4.1.12) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zod: 4.1.12 + zustand: 5.0.8(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + optionalDependencies: + '@tanstack/react-query': 5.90.8(react@19.2.1) + react: 19.2.1 + typescript: 5.8.3 + wagmi: 2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) + transitivePeerDependencies: + - '@types/react' + - immer + - use-sync-external-store + + porto@0.2.19(@tanstack/react-query@5.90.8(react@19.2.1))(@wagmi/core@2.22.1(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)): + dependencies: + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + hono: 4.10.2 + idb-keyval: 6.2.2 + mipd: 0.0.7(typescript@5.8.3) + ox: 0.9.12(typescript@5.8.3)(zod@4.1.12) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zod: 4.1.12 + zustand: 5.0.8(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + optionalDependencies: + '@tanstack/react-query': 5.90.8(react@19.2.1) + react: 19.2.1 + typescript: 5.8.3 + wagmi: 2.18.2(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) + transitivePeerDependencies: + - '@types/react' + - immer + - use-sync-external-store + possible-typed-array-names@1.1.0: {} postcss-import@15.1.0(postcss@8.5.6): @@ -12633,37 +16611,28 @@ snapshots: postcss: 8.5.6 postcss-value-parser: 4.2.0 read-cache: 1.0.0 - resolve: 1.22.10 + resolve: 1.22.11 - postcss-js@4.0.1(postcss@8.5.6): + postcss-js@4.1.0(postcss@8.5.6): dependencies: camelcase-css: 2.0.1 postcss: 8.5.6 - postcss-load-config@4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.4)(typescript@5.8.3)): - dependencies: - lilconfig: 3.1.3 - yaml: 2.8.0 - optionalDependencies: - postcss: 8.5.6 - ts-node: 10.9.2(@types/node@20.19.4)(typescript@5.8.3) - - postcss-load-config@4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@22.16.0)(typescript@5.8.3)): + postcss-load-config@4.0.2(postcss@8.5.6): dependencies: lilconfig: 3.1.3 - yaml: 2.8.0 + yaml: 2.8.1 optionalDependencies: postcss: 8.5.6 - ts-node: 10.9.2(@types/node@22.16.0)(typescript@5.8.3) - postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(yaml@2.8.0): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(yaml@2.8.1): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 1.21.7 postcss: 8.5.6 tsx: 4.20.3 - yaml: 2.8.0 + yaml: 2.8.1 postcss-nested@6.2.0(postcss@8.5.6): dependencies: @@ -12689,7 +16658,9 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - preact@10.26.9: {} + preact@10.24.2: {} + + preact@10.27.2: {} prelude-ls@1.2.1: {} @@ -12703,6 +16674,11 @@ snapshots: process-warning@1.0.0: {} + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -12723,7 +16699,7 @@ snapshots: bn.js: 4.12.2 browserify-rsa: 4.1.1 create-hash: 1.2.0 - parse-asn1: 5.1.7 + parse-asn1: 5.1.9 randombytes: 2.1.0 safe-buffer: 5.2.1 @@ -12782,6 +16758,11 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + react-dom@19.2.0(react@19.2.0): + dependencies: + react: 19.2.0 + scheduler: 0.27.0 + react-dom@19.2.1(react@19.2.1): dependencies: react: 19.2.1 @@ -12789,6 +16770,8 @@ snapshots: react-is@16.13.1: {} + react@19.2.0: {} + react@19.2.1: {} read-cache@1.0.0: @@ -12830,7 +16813,7 @@ snapshots: get-proto: 1.0.1 which-builtin-type: 1.2.1 - regenerate-unicode-properties@10.2.0: + regenerate-unicode-properties@10.2.2: dependencies: regenerate: 1.4.2 @@ -12845,23 +16828,25 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 - regexpu-core@6.2.0: + regexpu-core@6.4.0: dependencies: regenerate: 1.4.2 - regenerate-unicode-properties: 10.2.0 + regenerate-unicode-properties: 10.2.2 regjsgen: 0.8.0 - regjsparser: 0.12.0 + regjsparser: 0.13.0 unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.2.0 + unicode-match-property-value-ecmascript: 2.2.1 regjsgen@0.8.0: {} - regjsparser@0.12.0: + regjsparser@0.13.0: dependencies: - jsesc: 3.0.2 + jsesc: 3.1.0 require-directory@2.1.1: {} + require-from-string@2.0.2: {} + require-main-filename@2.0.0: {} resolve-from@4.0.0: {} @@ -12870,7 +16855,7 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve@1.22.10: + resolve@1.22.11: dependencies: is-core-module: 2.16.1 path-parse: 1.0.7 @@ -12884,43 +16869,40 @@ snapshots: reusify@1.1.0: {} - ripemd160@2.0.1: - dependencies: - hash-base: 2.0.2 - inherits: 2.0.4 - - ripemd160@2.0.2: + ripemd160@2.0.3: dependencies: - hash-base: 3.0.5 + hash-base: 3.1.2 inherits: 2.0.4 - rollup@4.44.1: + rollup@4.52.5: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.44.1 - '@rollup/rollup-android-arm64': 4.44.1 - '@rollup/rollup-darwin-arm64': 4.44.1 - '@rollup/rollup-darwin-x64': 4.44.1 - '@rollup/rollup-freebsd-arm64': 4.44.1 - '@rollup/rollup-freebsd-x64': 4.44.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.44.1 - '@rollup/rollup-linux-arm-musleabihf': 4.44.1 - '@rollup/rollup-linux-arm64-gnu': 4.44.1 - '@rollup/rollup-linux-arm64-musl': 4.44.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.44.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.44.1 - '@rollup/rollup-linux-riscv64-gnu': 4.44.1 - '@rollup/rollup-linux-riscv64-musl': 4.44.1 - '@rollup/rollup-linux-s390x-gnu': 4.44.1 - '@rollup/rollup-linux-x64-gnu': 4.44.1 - '@rollup/rollup-linux-x64-musl': 4.44.1 - '@rollup/rollup-win32-arm64-msvc': 4.44.1 - '@rollup/rollup-win32-ia32-msvc': 4.44.1 - '@rollup/rollup-win32-x64-msvc': 4.44.1 + '@rollup/rollup-android-arm-eabi': 4.52.5 + '@rollup/rollup-android-arm64': 4.52.5 + '@rollup/rollup-darwin-arm64': 4.52.5 + '@rollup/rollup-darwin-x64': 4.52.5 + '@rollup/rollup-freebsd-arm64': 4.52.5 + '@rollup/rollup-freebsd-x64': 4.52.5 + '@rollup/rollup-linux-arm-gnueabihf': 4.52.5 + '@rollup/rollup-linux-arm-musleabihf': 4.52.5 + '@rollup/rollup-linux-arm64-gnu': 4.52.5 + '@rollup/rollup-linux-arm64-musl': 4.52.5 + '@rollup/rollup-linux-loong64-gnu': 4.52.5 + '@rollup/rollup-linux-ppc64-gnu': 4.52.5 + '@rollup/rollup-linux-riscv64-gnu': 4.52.5 + '@rollup/rollup-linux-riscv64-musl': 4.52.5 + '@rollup/rollup-linux-s390x-gnu': 4.52.5 + '@rollup/rollup-linux-x64-gnu': 4.52.5 + '@rollup/rollup-linux-x64-musl': 4.52.5 + '@rollup/rollup-openharmony-arm64': 4.52.5 + '@rollup/rollup-win32-arm64-msvc': 4.52.5 + '@rollup/rollup-win32-ia32-msvc': 4.52.5 + '@rollup/rollup-win32-x64-gnu': 4.52.5 + '@rollup/rollup-win32-x64-msvc': 4.52.5 fsevents: 2.3.3 - rpc-websockets@9.1.1: + rpc-websockets@9.2.0: dependencies: '@swc/helpers': 0.5.17 '@types/uuid': 8.3.4 @@ -12974,7 +16956,7 @@ snapshots: semver@6.3.1: {} - semver@7.7.2: {} + semver@7.7.3: {} send@0.19.0: dependencies: @@ -13033,35 +17015,36 @@ snapshots: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 - to-buffer: 1.2.1 + to-buffer: 1.2.2 - sharp@0.34.2: + sharp@0.34.4: dependencies: - color: 4.2.3 - detect-libc: 2.0.4 - semver: 7.7.2 + '@img/colour': 1.0.0 + detect-libc: 2.1.2 + semver: 7.7.3 optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.2 - '@img/sharp-darwin-x64': 0.34.2 - '@img/sharp-libvips-darwin-arm64': 1.1.0 - '@img/sharp-libvips-darwin-x64': 1.1.0 - '@img/sharp-libvips-linux-arm': 1.1.0 - '@img/sharp-libvips-linux-arm64': 1.1.0 - '@img/sharp-libvips-linux-ppc64': 1.1.0 - '@img/sharp-libvips-linux-s390x': 1.1.0 - '@img/sharp-libvips-linux-x64': 1.1.0 - '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 - '@img/sharp-libvips-linuxmusl-x64': 1.1.0 - '@img/sharp-linux-arm': 0.34.2 - '@img/sharp-linux-arm64': 0.34.2 - '@img/sharp-linux-s390x': 0.34.2 - '@img/sharp-linux-x64': 0.34.2 - '@img/sharp-linuxmusl-arm64': 0.34.2 - '@img/sharp-linuxmusl-x64': 0.34.2 - '@img/sharp-wasm32': 0.34.2 - '@img/sharp-win32-arm64': 0.34.2 - '@img/sharp-win32-ia32': 0.34.2 - '@img/sharp-win32-x64': 0.34.2 + '@img/sharp-darwin-arm64': 0.34.4 + '@img/sharp-darwin-x64': 0.34.4 + '@img/sharp-libvips-darwin-arm64': 1.2.3 + '@img/sharp-libvips-darwin-x64': 1.2.3 + '@img/sharp-libvips-linux-arm': 1.2.3 + '@img/sharp-libvips-linux-arm64': 1.2.3 + '@img/sharp-libvips-linux-ppc64': 1.2.3 + '@img/sharp-libvips-linux-s390x': 1.2.3 + '@img/sharp-libvips-linux-x64': 1.2.3 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 + '@img/sharp-linux-arm': 0.34.4 + '@img/sharp-linux-arm64': 0.34.4 + '@img/sharp-linux-ppc64': 0.34.4 + '@img/sharp-linux-s390x': 0.34.4 + '@img/sharp-linux-x64': 0.34.4 + '@img/sharp-linuxmusl-arm64': 0.34.4 + '@img/sharp-linuxmusl-x64': 0.34.4 + '@img/sharp-wasm32': 0.34.4 + '@img/sharp-win32-arm64': 0.34.4 + '@img/sharp-win32-ia32': 0.34.4 + '@img/sharp-win32-x64': 0.34.4 optional: true shebang-command@2.0.0: @@ -13104,10 +17087,7 @@ snapshots: signal-exit@4.1.0: {} - simple-swizzle@0.2.2: - dependencies: - is-arrayish: 0.3.2 - optional: true + sisteransi@1.0.5: {} slash@3.0.0: {} @@ -13119,7 +17099,7 @@ snapshots: socket.io-client@4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 + debug: 4.3.4 engine.io-client: 6.6.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) socket.io-parser: 4.2.4 transitivePeerDependencies: @@ -13130,7 +17110,7 @@ snapshots: socket.io-parser@4.2.4: dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 + debug: 4.3.4 transitivePeerDependencies: - supports-color @@ -13149,9 +17129,9 @@ snapshots: spdx-expression-parse@4.0.0: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.21 + spdx-license-ids: 3.0.22 - spdx-license-ids@3.0.21: {} + spdx-license-ids@3.0.22: {} split-on-first@1.1.0: {} @@ -13163,7 +17143,7 @@ snapshots: statuses@2.0.1: {} - std-env@3.9.0: {} + std-env@3.10.0: {} stop-iteration-iterator@1.1.0: dependencies: @@ -13183,8 +17163,6 @@ snapshots: stream-shift@1.0.3: {} - streamsearch@1.1.0: {} - strict-uri-encode@2.0.0: {} string-width@4.2.3: @@ -13197,7 +17175,7 @@ snapshots: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 string.prototype.includes@2.0.1: dependencies: @@ -13261,9 +17239,9 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: + strip-ansi@7.1.2: dependencies: - ansi-regex: 6.1.0 + ansi-regex: 6.2.2 strip-bom@3.0.0: {} @@ -13271,20 +17249,20 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@3.0.0: + strip-literal@3.1.0: dependencies: js-tokens: 9.0.1 - styled-jsx@5.1.6(@babel/core@7.28.0)(react@19.2.1): + styled-jsx@5.1.6(@babel/core@7.28.4)(react@19.2.1): dependencies: client-only: 0.0.1 react: 19.2.1 optionalDependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.4 sucrase@3.35.0: dependencies: - '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 glob: 10.4.5 lines-and-columns: 1.2.4 @@ -13316,13 +17294,13 @@ snapshots: symbol-tree@3.2.4: {} - synckit@0.11.8: + synckit@0.11.11: dependencies: - '@pkgr/core': 0.2.7 + '@pkgr/core': 0.2.9 tailwind-merge@2.6.0: {} - tailwindcss@3.4.17(ts-node@10.9.2(@types/node@20.19.4)(typescript@5.8.3)): + tailwindcss@3.4.18(tsx@4.20.3)(yaml@2.8.1): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -13340,14 +17318,15 @@ snapshots: picocolors: 1.1.1 postcss: 8.5.6 postcss-import: 15.1.0(postcss@8.5.6) - postcss-js: 4.0.1(postcss@8.5.6) - postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.4)(typescript@5.8.3)) + postcss-js: 4.1.0(postcss@8.5.6) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(yaml@2.8.1) postcss-nested: 6.2.0(postcss@8.5.6) postcss-selector-parser: 6.1.2 - resolve: 1.22.10 + resolve: 1.22.11 sucrase: 3.35.0 transitivePeerDependencies: - - ts-node + - tsx + - yaml text-encoding-utf-8@1.0.2: {} @@ -13367,16 +17346,16 @@ snapshots: tinyexec@0.3.2: {} - tinyglobby@0.2.14: + tinyglobby@0.2.15: dependencies: - fdir: 6.4.6(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 tinypool@1.1.1: {} tinyrainbow@2.0.0: {} - tinyspy@4.0.3: {} + tinyspy@4.0.4: {} tldts-core@6.1.86: {} @@ -13384,7 +17363,7 @@ snapshots: dependencies: tldts-core: 6.1.86 - to-buffer@1.2.1: + to-buffer@1.2.2: dependencies: isarray: 2.0.5 safe-buffer: 5.2.1 @@ -13418,44 +17397,6 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-node@10.9.2(@types/node@20.19.4)(typescript@5.8.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 20.19.4 - acorn: 8.15.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.8.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - optional: true - - ts-node@10.9.2(@types/node@22.16.0)(typescript@5.8.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 22.16.0 - acorn: 8.15.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.8.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - optional: true - tsconfck@3.1.6(typescript@5.8.3): optionalDependencies: typescript: 5.8.3 @@ -13471,19 +17412,19 @@ snapshots: tslib@2.8.1: {} - tsup@7.3.0(postcss@8.5.6)(ts-node@10.9.2(@types/node@22.16.0)(typescript@5.8.3))(typescript@5.8.3): + tsup@7.3.0(postcss@8.5.6)(typescript@5.8.3): dependencies: bundle-require: 4.2.1(esbuild@0.19.12) cac: 6.7.14 chokidar: 3.6.0 - debug: 4.4.1 + debug: 4.4.3 esbuild: 0.19.12 execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@22.16.0)(typescript@5.8.3)) + postcss-load-config: 4.0.2(postcss@8.5.6) resolve-from: 5.0.0 - rollup: 4.44.1 + rollup: 4.52.5 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 @@ -13494,24 +17435,24 @@ snapshots: - supports-color - ts-node - tsup@8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0): + tsup@8.5.0(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.1): dependencies: bundle-require: 5.1.0(esbuild@0.25.5) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 - debug: 4.4.1 + debug: 4.4.3 esbuild: 0.25.5 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(yaml@2.8.0) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.20.3)(yaml@2.8.1) resolve-from: 5.0.0 - rollup: 4.44.1 + rollup: 4.52.5 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tinyexec: 0.3.2 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 tree-kill: 1.2.2 optionalDependencies: postcss: 8.5.6 @@ -13571,6 +17512,17 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 + typescript-eslint@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.8.3) + eslint: 9.38.0(jiti@1.21.7) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + typescript@5.8.3: {} ufo@1.6.1: {} @@ -13597,54 +17549,54 @@ snapshots: unicode-match-property-ecmascript@2.0.0: dependencies: unicode-canonical-property-names-ecmascript: 2.0.1 - unicode-property-aliases-ecmascript: 2.1.0 + unicode-property-aliases-ecmascript: 2.2.0 - unicode-match-property-value-ecmascript@2.2.0: {} + unicode-match-property-value-ecmascript@2.2.1: {} - unicode-property-aliases-ecmascript@2.1.0: {} + unicode-property-aliases-ecmascript@2.2.0: {} unpipe@1.0.0: {} - unrs-resolver@1.10.1: + unrs-resolver@1.11.1: dependencies: - napi-postinstall: 0.3.0 + napi-postinstall: 0.3.4 optionalDependencies: - '@unrs/resolver-binding-android-arm-eabi': 1.10.1 - '@unrs/resolver-binding-android-arm64': 1.10.1 - '@unrs/resolver-binding-darwin-arm64': 1.10.1 - '@unrs/resolver-binding-darwin-x64': 1.10.1 - '@unrs/resolver-binding-freebsd-x64': 1.10.1 - '@unrs/resolver-binding-linux-arm-gnueabihf': 1.10.1 - '@unrs/resolver-binding-linux-arm-musleabihf': 1.10.1 - '@unrs/resolver-binding-linux-arm64-gnu': 1.10.1 - '@unrs/resolver-binding-linux-arm64-musl': 1.10.1 - '@unrs/resolver-binding-linux-ppc64-gnu': 1.10.1 - '@unrs/resolver-binding-linux-riscv64-gnu': 1.10.1 - '@unrs/resolver-binding-linux-riscv64-musl': 1.10.1 - '@unrs/resolver-binding-linux-s390x-gnu': 1.10.1 - '@unrs/resolver-binding-linux-x64-gnu': 1.10.1 - '@unrs/resolver-binding-linux-x64-musl': 1.10.1 - '@unrs/resolver-binding-wasm32-wasi': 1.10.1 - '@unrs/resolver-binding-win32-arm64-msvc': 1.10.1 - '@unrs/resolver-binding-win32-ia32-msvc': 1.10.1 - '@unrs/resolver-binding-win32-x64-msvc': 1.10.1 - - unstorage@1.16.0(idb-keyval@6.2.2): + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + + unstorage@1.17.1(idb-keyval@6.2.2): dependencies: anymatch: 3.1.3 chokidar: 4.0.3 destr: 2.0.5 - h3: 1.15.3 + h3: 1.15.4 lru-cache: 10.4.3 - node-fetch-native: 1.6.6 + node-fetch-native: 1.6.7 ofetch: 1.4.1 ufo: 1.6.1 optionalDependencies: idb-keyval: 6.2.2 - update-browserslist-db@1.1.3(browserslist@4.25.1): + update-browserslist-db@1.1.4(browserslist@4.27.0): dependencies: - browserslist: 4.25.1 + browserslist: 4.27.0 escalade: 3.2.0 picocolors: 1.1.1 @@ -13652,10 +17604,18 @@ snapshots: dependencies: punycode: 2.3.1 + use-sync-external-store@1.2.0(react@19.2.0): + dependencies: + react: 19.2.0 + use-sync-external-store@1.2.0(react@19.2.1): dependencies: react: 19.2.1 + use-sync-external-store@1.4.0(react@19.2.0): + dependencies: + react: 19.2.0 + use-sync-external-store@1.4.0(react@19.2.1): dependencies: react: 19.2.1 @@ -13670,7 +17630,7 @@ snapshots: dependencies: inherits: 2.0.4 is-arguments: 1.2.0 - is-generator-function: 1.1.0 + is-generator-function: 1.1.2 is-typed-array: 1.1.15 which-typed-array: 1.1.19 @@ -13680,16 +17640,30 @@ snapshots: uuid@9.0.1: {} - v8-compile-cache-lib@3.0.1: - optional: true + valtio@1.13.2(@types/react@19.2.2)(react@19.2.0): + dependencies: + derive-valtio: 0.1.0(valtio@1.13.2(@types/react@19.2.2)(react@19.2.0)) + proxy-compare: 2.6.0 + use-sync-external-store: 1.2.0(react@19.2.0) + optionalDependencies: + '@types/react': 19.2.2 + react: 19.2.0 + + valtio@1.13.2(@types/react@19.2.2)(react@19.2.1): + dependencies: + derive-valtio: 0.1.0(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1)) + proxy-compare: 2.6.0 + use-sync-external-store: 1.2.0(react@19.2.1) + optionalDependencies: + '@types/react': 19.2.2 + react: 19.2.1 - valtio@1.13.2(@types/react@19.1.8)(react@19.2.1): + valtio@1.13.2(react@19.2.1): dependencies: - derive-valtio: 0.1.0(valtio@1.13.2(@types/react@19.1.8)(react@19.2.1)) + derive-valtio: 0.1.0(valtio@1.13.2(react@19.2.1)) proxy-compare: 2.6.0 use-sync-external-store: 1.2.0(react@19.2.1) optionalDependencies: - '@types/react': 19.1.8 react: 19.2.1 vary@1.1.2: {} @@ -13711,15 +17685,15 @@ snapshots: - utf-8-validate - zod - viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.22.4): + viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71): dependencies: '@noble/curves': 1.9.2 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.0.8(typescript@5.8.3)(zod@3.22.4) + abitype: 1.0.8(typescript@5.8.3)(zod@3.25.71) isows: 1.0.7(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - ox: 0.8.1(typescript@5.8.3)(zod@3.22.4) + ox: 0.8.1(typescript@5.8.3)(zod@3.25.71) ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: typescript: 5.8.3 @@ -13728,16 +17702,67 @@ snapshots: - utf-8-validate - zod - viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71): + viem@2.38.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71): dependencies: - '@noble/curves': 1.9.2 + '@noble/curves': 1.9.1 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.0.8(typescript@5.8.3)(zod@3.25.71) - isows: 1.0.7(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - ox: 0.8.1(typescript@5.8.3)(zod@3.25.71) - ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + abitype: 1.1.0(typescript@5.8.3)(zod@3.25.71) + isows: 1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + ox: 0.9.6(typescript@5.8.3)(zod@3.25.71) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + viem@2.38.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@4.1.12): + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.1.0(typescript@5.8.3)(zod@4.1.12) + isows: 1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + ox: 0.9.6(typescript@5.8.3)(zod@4.1.12) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.22.4): + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.1.0(typescript@5.8.3)(zod@3.22.4) + isows: 1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + ox: 0.9.6(typescript@5.8.3)(zod@3.22.4) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71): + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.1.0(typescript@5.8.3)(zod@3.25.71) + isows: 1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + ox: 0.9.6(typescript@5.8.3)(zod@3.25.71) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: @@ -13745,13 +17770,13 @@ snapshots: - utf-8-validate - zod - vite-node@3.2.4(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0): + vite-node@3.2.4(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1): dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -13766,56 +17791,56 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0)): + vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)): dependencies: - debug: 4.4.1 + debug: 4.4.3 globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.8.3) optionalDependencies: - vite: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) transitivePeerDependencies: - supports-color - typescript - vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0): + vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1): dependencies: esbuild: 0.25.5 - fdir: 6.4.6(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.44.1 - tinyglobby: 0.2.14 + rollup: 4.52.5 + tinyglobby: 0.2.15 optionalDependencies: '@types/node': 22.16.0 fsevents: 2.3.3 jiti: 1.21.7 tsx: 4.20.3 - yaml: 2.8.0 + yaml: 2.8.1 - vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.0): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.16.0)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(tsx@4.20.3)(yaml@2.8.1): dependencies: - '@types/chai': 5.2.2 + '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0)) + '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 '@vitest/spy': 3.2.4 '@vitest/utils': 3.2.4 - chai: 5.2.0 - debug: 4.4.1 - expect-type: 1.2.1 - magic-string: 0.30.17 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.2.2 + magic-string: 0.30.19 pathe: 2.0.3 - picomatch: 4.0.2 - std-env: 3.9.0 + picomatch: 4.0.3 + std-env: 3.10.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) - vite-node: 3.2.4(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.0) + vite: 6.4.1(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@22.16.0)(jiti@1.21.7)(tsx@4.20.3)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 @@ -13839,11 +17864,50 @@ snapshots: dependencies: xml-name-validator: 5.0.0 - wagmi@2.15.6(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.2.1))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71): + wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71): + dependencies: + '@tanstack/react-query': 5.90.8(react@19.2.0) + '@wagmi/connectors': 6.1.0(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.0))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.0))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + react: 19.2.0 + use-sync-external-store: 1.4.0(react@19.2.0) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/query-core' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - supports-color + - uploadthing + - utf-8-validate + - zod + + wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71): dependencies: - '@tanstack/react-query': 5.81.5(react@19.2.1) - '@wagmi/connectors': 5.8.5(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) - '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@tanstack/react-query': 5.90.8(react@19.2.1) + '@wagmi/connectors': 6.1.0(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) viem: 2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) @@ -13865,6 +17929,85 @@ snapshots: - '@types/react' - '@upstash/redis' - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - supports-color + - uploadthing + - utf-8-validate + - zod + + wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71): + dependencies: + '@tanstack/react-query': 5.90.8(react@19.2.1) + '@wagmi/connectors': 6.1.0(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.31.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + react: 19.2.1 + use-sync-external-store: 1.4.0(react@19.2.1) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/query-core' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - supports-color + - uploadthing + - utf-8-validate + - zod + + wagmi@2.18.2(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71): + dependencies: + '@tanstack/react-query': 5.90.8(react@19.2.1) + '@wagmi/connectors': 6.1.0(@tanstack/react-query@5.90.8(react@19.2.1))(@wagmi/core@2.22.1(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(wagmi@2.18.2(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71))(zod@3.25.71) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.8)(@types/react@19.2.2)(react@19.2.1)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + react: 19.2.1 + use-sync-external-store: 1.4.0(react@19.2.1) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/query-core' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' - '@vercel/kv' - aws4fetch - bufferutil @@ -13923,7 +18066,7 @@ snapshots: is-async-function: 2.1.1 is-date-object: 1.1.0 is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.0 + is-generator-function: 1.1.2 is-regex: 1.2.1 is-weakref: 1.1.1 isarray: 2.0.5 @@ -13975,9 +18118,9 @@ snapshots: wrap-ansi@8.1.0: dependencies: - ansi-styles: 6.2.1 + ansi-styles: 6.2.3 string-width: 5.1.2 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 wrappy@1.0.2: {} @@ -14006,6 +18149,55 @@ snapshots: bufferutil: 4.0.9 utf-8-validate: 5.0.10 + x402@0.7.3(@solana/sysvars@5.0.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)): + dependencies: + '@scure/base': 1.2.6 + '@solana-program/compute-budget': 0.11.0(@solana/kit@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token': 0.9.0(@solana/kit@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token-2022': 0.6.1(@solana/kit@5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@5.0.0(typescript@5.8.3)) + '@solana/kit': 5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': 5.0.0(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/wallet-standard-features': 1.3.0 + '@wallet-standard/app': 1.1.0 + '@wallet-standard/base': 1.1.0 + '@wallet-standard/features': 1.1.0 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + wagmi: 2.18.2(@tanstack/react-query@5.90.8(react@19.2.1))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71) + zod: 3.25.71 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@solana/sysvars' + - '@tanstack/query-core' + - '@tanstack/react-query' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - fastestsmallesttextencoderdecoder + - immer + - ioredis + - react + - supports-color + - typescript + - uploadthing + - utf-8-validate + - ws + xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} @@ -14018,7 +18210,7 @@ snapshots: yallist@3.1.1: {} - yaml@2.8.0: {} + yaml@2.8.1: {} yargs-parser@18.1.3: dependencies: @@ -14039,17 +18231,50 @@ snapshots: y18n: 4.0.3 yargs-parser: 18.1.3 - yn@3.1.1: - optional: true - yocto-queue@0.1.0: {} + zod-validation-error@4.0.2(zod@3.25.71): + dependencies: + zod: 3.25.71 + zod@3.22.4: {} zod@3.25.71: {} - zustand@5.0.0(@types/react@19.1.8)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)): + zod@4.1.12: {} + + zustand@5.0.0(@types/react@19.2.2)(react@19.2.0)(use-sync-external-store@1.4.0(react@19.2.0)): + optionalDependencies: + '@types/react': 19.2.2 + react: 19.2.0 + use-sync-external-store: 1.4.0(react@19.2.0) + + zustand@5.0.0(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)): + optionalDependencies: + '@types/react': 19.2.2 + react: 19.2.1 + use-sync-external-store: 1.4.0(react@19.2.1) + + zustand@5.0.3(@types/react@19.2.2)(react@19.2.0)(use-sync-external-store@1.4.0(react@19.2.0)): + optionalDependencies: + '@types/react': 19.2.2 + react: 19.2.0 + use-sync-external-store: 1.4.0(react@19.2.0) + + zustand@5.0.3(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)): + optionalDependencies: + '@types/react': 19.2.2 + react: 19.2.1 + use-sync-external-store: 1.4.0(react@19.2.1) + + zustand@5.0.8(@types/react@19.2.2)(react@19.2.0)(use-sync-external-store@1.4.0(react@19.2.0)): + optionalDependencies: + '@types/react': 19.2.2 + react: 19.2.0 + use-sync-external-store: 1.4.0(react@19.2.0) + + zustand@5.0.8(@types/react@19.2.2)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)): optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.2.2 react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) diff --git a/e2e/pnpm-workspace.yaml b/e2e/pnpm-workspace.yaml index 752368a67..190cf9d2a 100644 --- a/e2e/pnpm-workspace.yaml +++ b/e2e/pnpm-workspace.yaml @@ -1,4 +1,13 @@ packages: + - "facilitators/*" + - "facilitators/external-proxies/*" + - "facilitators/external-proxies/local/*" - "servers/*" - "clients/*" + - "clients/external/*" + - "legacy/servers/*" + - "legacy/clients/*" - "../typescript/packages/*" + - "../typescript/packages/http/*" + - "../typescript/packages/mechanisms/*" + - "../typescript/packages/legacy/*" diff --git a/e2e/servers/express/README.md b/e2e/servers/express/README.md index 5adab235c..c28f19f80 100644 --- a/e2e/servers/express/README.md +++ b/e2e/servers/express/README.md @@ -1,146 +1,170 @@ -# x402-express Example Server +# E2E Test Server: Express (TypeScript) -This is an example Express.js server that demonstrates how to use the `x402-express` middleware to implement paywall functionality in your API endpoints. +This server demonstrates and tests the x402 Express.js middleware with both EVM and SVM payment protection. -## Prerequisites +## What It Tests -- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) -- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) -- A valid Ethereum address for receiving payments -- Coinbase Developer Platform API Key & Secret (if accepting payments on Base mainnet) - -- Get them here [https://portal.cdp.coinbase.com/projects](https://portal.cdp.coinbase.com/projects) +### Core Functionality +- ✅ **V2 Protocol** - Modern x402 server middleware +- ✅ **Payment Protection** - Middleware protecting specific routes +- ✅ **Multi-chain Support** - EVM and SVM payment acceptance +- ✅ **Facilitator Integration** - HTTP communication with facilitator +- ✅ **Extension Support** - Bazaar discovery metadata +- ✅ **Settlement Handling** - Payment verification and confirmation -## Setup +### Protected Endpoints +- ✅ `GET /protected` - Requires EVM payment (USDC on Base Sepolia) +- ✅ `GET /protected-svm` - Requires SVM payment (USDC on Solana Devnet) -1. Copy `.env-local` to `.env` and add your Ethereum address to receive payments: +## What It Demonstrates -```bash -cp .env-local .env -``` +### Server Setup -2. Install and build all packages from the typescript examples root: -```bash -cd ../../ -pnpm install -pnpm build -cd servers/express -``` +```typescript +import express from "express"; +import { x402Middleware } from "@x402/server/express"; +import { ExactEvmServer } from "@x402/evm"; +import { ExactEvmServer } from "@x402/svm"; + +const app = express(); + +// Define payment requirements for routes +const routes = { + "GET /protected": { + scheme: "exact", + network: "eip155:84532", + payTo: "0xYourAddress", + price: "$0.001", + extensions: { + bazaar: discoveryMetadata + } + }, + "GET /protected-svm": { + scheme: "exact", + network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + payTo: "YourSolanaAddress", + price: "$0.001", + extensions: { + bazaar: discoveryMetadata + } + } +}; + +// Apply x402 middleware with EVM and SVM servers +app.use(x402Middleware({ + routes, + facilitatorUrl: "http://localhost:4023", + servers: { + "eip155:84532": new ExactEvmServer(), + "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1": new ExactSvmServer() + } +})); -3. Run the server -```bash -pnpm install -pnpm dev +// Define protected endpoints +app.get("/protected", (req, res) => { + res.json({ message: "EVM payment successful!" }); +}); + +app.get("/protected-svm", (req, res) => { + res.json({ message: "SVM payment successful!" }); +}); ``` -## Testing the Server +### Key Concepts Shown -You can test the server using one of the example clients: +1. **Route-Based Configuration** - Payment requirements per route +2. **Multi-Chain Services** - Different services for different networks +3. **Price Parsing** - Dollar amounts converted to token units +4. **Facilitator Client** - HTTP communication with payment processor +5. **Extension Metadata** - Bazaar discovery info embedded in responses +6. **Automatic 402 Responses** - Middleware generates payment requirements -### Using the Fetch Client -```bash -cd ../clients/fetch -# Ensure .env is setup -pnpm install -pnpm dev -``` +## Test Scenarios + +This server is tested with: +- **Clients:** TypeScript Fetch, Go HTTP +- **Facilitators:** TypeScript, Go +- **Payment Types:** EVM (Base Sepolia), SVM (Solana Devnet) +- **Protocols:** V2 (primary), V1 (via client negotiation) + +### Request Flow +1. Client makes initial request (no payment) +2. Middleware returns 402 with payment requirements +3. Client creates payment payload +4. Client retries with payment signature +5. Middleware verifies payment via facilitator +6. Middleware returns protected content + +## Running -### Using the Axios Client ```bash -cd ../clients/axios -# Ensure .env is setup -pnpm install -pnpm dev +# Via e2e test suite +cd e2e +pnpm test --server=express + +# Direct execution +cd e2e/servers/express +export FACILITATOR_URL="http://localhost:4023" +export EVM_PAYEE_ADDRESS="0x..." +export SVM_PAYEE_ADDRESS="..." +export PORT=4022 +pnpm start ``` -These clients will demonstrate how to: -1. Make an initial request to get payment requirements -2. Process the payment requirements -3. Make a second request with the payment token +## Environment Variables -## Example Endpoint +- `PORT` - HTTP server port (default: 4022) +- `FACILITATOR_URL` - Facilitator endpoint URL +- `EVM_PAYEE_ADDRESS` - Ethereum address to receive payments +- `SVM_PAYEE_ADDRESS` - Solana address to receive payments +- `EVM_NETWORK` - EVM network (default: eip155:84532) +- `SVM_NETWORK` - SVM network (default: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1) -The server includes a single example endpoint at `/weather` that requires a payment of $0.001 to access. The endpoint returns a simple weather report. +## Response Examples -## Response Format +### 402 Payment Required (No Payment Sent) -### Payment Required (402) -```json -{ - "error": "X-PAYMENT header is required", - "paymentRequirements": { - "scheme": "exact", - "network": "base", - "maxAmountRequired": "1000", - "resource": "http://localhost:4021/weather", - "description": "", - "mimeType": "", - "payTo": "0xYourAddress", - "maxTimeoutSeconds": 60, - "asset": "0x...", - "outputSchema": null, - "extra": null - } -} ``` +HTTP/1.1 402 Payment Required +PAYMENT-REQUIRED: -### Successful Response -```ts -// Body { - "report": { - "weather": "sunny", - "temperature": 70 - } + "error": "Payment required", + "x402Version": 2, + "accepts": [...] } -// Headers +``` + +### 200 Success (Payment Verified) + +``` +HTTP/1.1 200 OK +PAYMENT-RESPONSE: + { - "X-PAYMENT-RESPONSE": "..." // Encoded response object + "message": "Protected endpoint accessed successfully" } ``` -## Extending the Example +## Package Dependencies -To add more paid endpoints, follow this pattern: +- `@x402/server` - Express middleware +- `@x402/evm` - EVM server +- `@x402/svm` - SVM server +- `@x402/extensions/bazaar` - Discovery extension +- `express` - HTTP server framework -```typescript -// First, configure the payment middleware with your routes -app.use( - paymentMiddleware( - payTo, - { - // Define your routes and their payment requirements - "GET /your-endpoint": { - price: "$0.10", - network: "base-sepolia", - }, - "/premium/*": { - price: { - amount: "100000", - asset: { - address: "0xabc", - decimals: 18, - eip712: { - name: "WETH", - version: "1", - }, - }, - }, - network: "base-sepolia", - }, - }, - ), -); - -// Then define your routes as normal -app.get("/your-endpoint", (req, res) => { - res.json({ - // Your response data - }); -}); +## Implementation Highlights -app.get("/premium/content", (req, res) => { - res.json({ - content: "This is premium content", - }); -}); -``` +### Middleware Features +- **Automatic 402 Responses** - Generates payment requirements +- **Payment Verification** - Validates via facilitator +- **Settlement Tracking** - Includes payment response headers +- **Extension Support** - Embeds bazaar metadata +- **Error Handling** - Clear error messages for payment failures + +### Service Integration +- **EVM Server** - Handles Base Sepolia USDC payments +- **SVM Server** - Handles Solana Devnet USDC payments +- **Price Conversion** - "$0.001" → token amounts with decimals +- **Asset Resolution** - Automatic USDC contract/mint lookup diff --git a/e2e/servers/express/build.sh b/e2e/servers/express/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/servers/express/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/servers/express/index.ts b/e2e/servers/express/index.ts index a7647eb6b..f4c6afc6f 100644 --- a/e2e/servers/express/index.ts +++ b/e2e/servers/express/index.ts @@ -1,50 +1,132 @@ import express from "express"; -import { Network, paymentMiddleware, SolanaAddress } from "x402-express"; -import { facilitator } from "@coinbase/x402"; +import { paymentMiddleware } from "@x402/express"; +import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; +import { registerExactEvmScheme } from "@x402/evm/exact/server"; +import { registerExactSvmScheme } from "@x402/svm/exact/server"; +import { bazaarResourceServerExtension, declareDiscoveryExtension } from "@x402/extensions/bazaar"; import dotenv from "dotenv"; dotenv.config(); -const useCdpFacilitator = process.env.USE_CDP_FACILITATOR === 'true'; -const evmNetwork = process.env.EVM_NETWORK as Network; -const svmNetwork = process.env.SVM_NETWORK as Network; -const payToEvm = process.env.EVM_ADDRESS as `0x${string}`; -const payToSvm = process.env.SVM_ADDRESS as SolanaAddress; -const port = process.env.PORT || "4021"; +/** + * Express E2E Test Server with x402 Payment Middleware + * + * This server demonstrates how to integrate x402 payment middleware + * with an Express application for end-to-end testing. + */ -if (!payToEvm || !evmNetwork) { - console.error("Missing required environment variables"); +const PORT = process.env.PORT || "4021"; +const EVM_NETWORK = "eip155:84532" as const; +const SVM_NETWORK = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" as `${string}:${string}`; +const EVM_PAYEE_ADDRESS = process.env.EVM_PAYEE_ADDRESS as `0x${string}`; +const SVM_PAYEE_ADDRESS = process.env.SVM_PAYEE_ADDRESS as string; +const facilitatorUrl = process.env.FACILITATOR_URL; + +if (!EVM_PAYEE_ADDRESS) { + console.error("❌ EVM_PAYEE_ADDRESS environment variable is required"); + process.exit(1); +} + +if (!SVM_PAYEE_ADDRESS) { + console.error("❌ SVM_PAYEE_ADDRESS environment variable is required"); + process.exit(1); +} + +if (!facilitatorUrl) { + console.error("❌ FACILITATOR_URL environment variable is required"); process.exit(1); } +// Initialize Express app const app = express(); +// Create HTTP facilitator client +const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl }); + +// Create x402 resource server +const server = new x402ResourceServer(facilitatorClient); + +// Register server schemes +registerExactEvmScheme(server); +registerExactSvmScheme(server); + +// Register Bazaar discovery extension +server.registerExtension(bazaarResourceServerExtension); + +console.log(`Facilitator account: ${process.env.EVM_PRIVATE_KEY ? process.env.EVM_PRIVATE_KEY.substring(0, 10) + '...' : 'not configured'}`); +console.log(`Using remote facilitator at: ${facilitatorUrl}`); + +/** + * Configure x402 payment middleware using builder pattern + * + * This middleware protects endpoints with $0.001 USDC payment requirements + * on Base Sepolia and Solana Devnet with bazaar discovery extension. + */ app.use( paymentMiddleware( - payToEvm, { + // Route-specific payment configuration "GET /protected": { - price: "$0.001", - network: evmNetwork, + accepts: { + payTo: EVM_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: EVM_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, }, - }, - useCdpFacilitator ? facilitator : undefined - ), -); - -app.use( - paymentMiddleware( - payToSvm, - { "GET /protected-svm": { - price: "$0.001", - network: svmNetwork, + accepts: { + payTo: SVM_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: SVM_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, }, }, - useCdpFacilitator ? facilitator : undefined + server, // Pass pre-configured server instance ), ); +/** + * Protected endpoint - requires payment to access + * + * This endpoint demonstrates a resource protected by x402 payment middleware. + * Clients must provide a valid payment signature to access this endpoint. + */ app.get("/protected", (req, res) => { res.json({ message: "Protected endpoint accessed successfully", @@ -52,23 +134,65 @@ app.get("/protected", (req, res) => { }); }); +/** + * Protected SVM endpoint - requires payment to access + * + * This endpoint demonstrates a resource protected by x402 payment middleware for SVM. + * Clients must provide a valid payment signature to access this endpoint. + */ app.get("/protected-svm", (req, res) => { res.json({ - message: "Protected endpoint #2 accessed successfully", + message: "Protected endpoint accessed successfully", timestamp: new Date().toISOString(), }); }); +/** + * Health check endpoint - no payment required + * + * Used to verify the server is running and responsive. + */ app.get("/health", (req, res) => { - res.json({ status: "ok" }); + res.json({ + status: "ok", + network: EVM_NETWORK, + payee: EVM_PAYEE_ADDRESS, + version: "2.0.0", + }); }); +/** + * Shutdown endpoint - used by e2e tests + * + * Allows graceful shutdown of the server during testing. + */ app.post("/close", (req, res) => { - res.json({ message: "Server shutting down" }); + res.json({ message: "Server shutting down gracefully" }); console.log("Received shutdown request"); - process.exit(0); + + // Give time for response to be sent + setTimeout(() => { + process.exit(0); + }, 100); }); -app.listen(parseInt(port), () => { - console.log(`Server listening at http://localhost:${port}`); -}); \ No newline at end of file +// Start the server +app.listen(parseInt(PORT), () => { + console.log(` +╔════════════════════════════════════════════════════════╗ +║ x402 Express E2E Test Server ║ +╠════════════════════════════════════════════════════════╣ +║ Server: http://localhost:${PORT} ║ +║ EVM Network: ${EVM_NETWORK} ║ +║ SVM Network: ${SVM_NETWORK} ║ +║ EVM Payee: ${EVM_PAYEE_ADDRESS} ║ +║ SVM Payee: ${SVM_PAYEE_ADDRESS} ║ +║ ║ +║ Endpoints: ║ +║ • GET /protected (requires $0.001 USDC payment) ║ +║ • GET /protected-svm (requires $0.001 USDC payment) ║ +║ • GET /health (no payment required) ║ +║ • POST /close (shutdown server) ║ +╚════════════════════════════════════════════════════════╝ + `); +}); diff --git a/e2e/servers/express/install.sh b/e2e/servers/express/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/servers/express/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/servers/express/package.json b/e2e/servers/express/package.json index c73330731..ec783ae2e 100644 --- a/e2e/servers/express/package.json +++ b/e2e/servers/express/package.json @@ -1,5 +1,5 @@ { - "name": "express-e2e", + "name": "@x402/express-e2e", "private": true, "type": "module", "scripts": { @@ -10,10 +10,13 @@ "lint:check": "eslint . --ext .ts" }, "dependencies": { - "@coinbase/x402": "workspace:*", + "@x402/core": "workspace:*", + "@x402/express": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/extensions": "workspace:*", + "@x402/svm": "workspace:*", "dotenv": "^16.6.1", - "express": "^4.18.2", - "x402-express": "workspace:*" + "express": "^4.18.2" }, "devDependencies": { "@eslint/js": "^9.24.0", diff --git a/e2e/servers/express/test.config.json b/e2e/servers/express/test.config.json index 0e426e6c7..4b2060b17 100644 --- a/e2e/servers/express/test.config.json +++ b/e2e/servers/express/test.config.json @@ -2,6 +2,10 @@ "name": "express", "type": "server", "language": "typescript", + "x402Version": 2, + "extensions": [ + "bazaar" + ], "endpoints": [ { "path": "/protected", @@ -33,15 +37,10 @@ "environment": { "required": [ "PORT", - "USE_CDP_FACILITATOR", - "EVM_NETWORK", - "SVM_NETWORK", - "EVM_ADDRESS", - "SVM_ADDRESS" + "EVM_PAYEE_ADDRESS", + "SVM_PAYEE_ADDRESS", + "FACILITATOR_URL" ], - "optional": [ - "CDP_API_KEY_ID", - "CDP_API_KEY_SECRET" - ] + "optional": [] } } \ No newline at end of file diff --git a/e2e/servers/gin/.gitignore b/e2e/servers/gin/.gitignore new file mode 100644 index 000000000..556a7128f --- /dev/null +++ b/e2e/servers/gin/.gitignore @@ -0,0 +1,8 @@ +# Binaries +gin-server +main + +# Environment files +.env +.env.local + diff --git a/e2e/servers/gin/README.md b/e2e/servers/gin/README.md new file mode 100644 index 000000000..66d0455a1 --- /dev/null +++ b/e2e/servers/gin/README.md @@ -0,0 +1,197 @@ +# E2E Test Server: Gin (Go) + +This server demonstrates and tests the x402 Gin middleware with both EVM and SVM payment protection. + +## What It Tests + +### Core Functionality +- ✅ **V2 Protocol** - Modern x402 server middleware +- ✅ **Payment Protection** - Middleware protecting specific routes +- ✅ **Multi-chain Support** - EVM and SVM payment acceptance +- ✅ **Facilitator Integration** - HTTP communication with facilitator +- ✅ **Extension Support** - Bazaar discovery metadata +- ✅ **Settlement Handling** - Payment verification and confirmation + +### Protected Endpoints +- ✅ `GET /protected` - Requires EVM payment (USDC on Base Sepolia) +- ✅ `GET /protected-svm` - Requires SVM payment (USDC on Solana Devnet) + +## What It Demonstrates + +### Server Setup + +```go +import ( + ginfw "github.com/gin-gonic/gin" + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + "github.com/coinbase/x402/go/http/gin" + "github.com/coinbase/x402/go/mechanisms/evm" + "github.com/coinbase/x402/go/mechanisms/svm" + "github.com/coinbase/x402/go/extensions/bazaar" +) + +// Create Gin router +r := ginfw.New() + +// Define payment routes +routes := x402http.RoutesConfig{ + "GET /protected": { + Scheme: "exact", + Network: "eip155:84532", + PayTo: evmPayeeAddress, + Price: "$0.001", + Extensions: map[string]interface{}{ + "bazaar": discoveryExtension, + }, + }, + "GET /protected-svm": { + Scheme: "exact", + Network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + PayTo: svmPayeeAddress, + Price: "$0.001", + Extensions: map[string]interface{}{ + "bazaar": discoveryExtension, + }, + }, +} + +// Create services +evmServer := evm.NewExactEvmServer() +svmServer := svm.NewExactEvmServer() + +// Apply payment middleware +r.Use(gin.PaymentMiddleware( + routes, + gin.WithFacilitatorClient(facilitatorClient), + gin.WithScheme("eip155:84532", evmServer), + gin.WithScheme("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", svmServer), + gin.WithInitializeOnStart(true), +)) + +// Define protected endpoints +r.GET("/protected", func(c *ginfw.Context) { + c.JSON(200, gin.H{"message": "EVM payment successful!"}) +}) + +r.GET("/protected-svm", func(c *ginfw.Context) { + c.JSON(200, gin.H{"message": "SVM payment successful!"}) +}) +``` + +### Key Concepts Shown + +1. **Route Configuration** - Map of route → payment requirements +2. **Multi-Chain Services** - Different services for EVM vs SVM +3. **Facilitator Client** - HTTP client for verification/settlement +4. **Middleware Options** - Functional options pattern +5. **Extension Integration** - Bazaar discovery declarations +6. **Automatic Initialization** - Service initialization on startup + +## Test Scenarios + +This server is tested with: +- **Clients:** TypeScript Fetch, Go HTTP +- **Facilitators:** TypeScript, Go +- **Payment Types:** EVM (Base Sepolia), SVM (Solana Devnet) +- **Protocols:** V2 (primary), V1 (via client negotiation) + +### Request Flow +1. Client makes initial request (no payment) +2. Middleware returns 402 with `PAYMENT-REQUIRED` header +3. Client creates payment payload +4. Client retries with `PAYMENT-SIGNATURE` header +5. Middleware forwards to facilitator for verification +6. Middleware returns protected content + `PAYMENT-RESPONSE` header + +## Running + +```bash +# Via e2e test suite +cd e2e +pnpm test --server=gin + +# Direct execution +cd e2e/servers/gin +export FACILITATOR_URL="http://localhost:4024" +export EVM_PAYEE_ADDRESS="0x..." +export SVM_PAYEE_ADDRESS="..." +export PORT=4023 +./gin +``` + +## Environment Variables + +- `PORT` - HTTP server port (default: 4023) +- `FACILITATOR_URL` - Facilitator endpoint URL +- `EVM_PAYEE_ADDRESS` - Ethereum address to receive payments +- `SVM_PAYEE_ADDRESS` - Solana address to receive payments +- `EVM_NETWORK` - EVM network (default: eip155:84532) +- `SVM_NETWORK` - SVM network (default: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1) + +## Response Examples + +### 402 Payment Required + +``` +HTTP/1.1 402 Payment Required +PAYMENT-REQUIRED: +Content-Type: application/json + +{ + "error": "Payment required", + "x402Version": 2, + "accepts": [...], + "resource": {...}, + "extensions": { + "bazaar": { + "method": "GET", + "outputExample": {...} + } + } +} +``` + +### 200 Success (After Payment) + +``` +HTTP/1.1 200 OK +PAYMENT-RESPONSE: +Content-Type: application/json + +{ + "message": "Protected endpoint accessed successfully", + "timestamp": "2024-01-01T00:00:00Z" +} +``` + +## Dependencies + +- `github.com/coinbase/x402/go` - Core x402 +- `github.com/coinbase/x402/go/http` - HTTP integration +- `github.com/coinbase/x402/go/http/gin` - Gin middleware +- `github.com/coinbase/x402/go/mechanisms/evm` - EVM server +- `github.com/coinbase/x402/go/mechanisms/svm` - SVM server +- `github.com/coinbase/x402/go/extensions/bazaar` - Discovery extension +- `github.com/gin-gonic/gin` - HTTP framework + +## Implementation Highlights + +### Middleware Features +- **Route Matching** - Pattern-based route configuration +- **Payment Requirement Building** - Automatic 402 response generation +- **Facilitator Communication** - HTTP client for verification +- **Settlement Callbacks** - Optional handlers for payment events +- **Extension Support** - Bazaar metadata in responses +- **Timeout Handling** - Configurable facilitator timeouts + +### Service Integration +- **EVM Server** - Base Sepolia USDC +- **SVM Server** - Solana Devnet USDC +- **Initialization** - Fetches supported kinds from facilitator +- **Price Parsing** - Dollar strings → token amounts + +### Bazaar Extension +- **Method Declaration** - GET with output schema +- **Example Output** - Response structure preview +- **Schema Definition** - JSON Schema for validation diff --git a/e2e/servers/gin/build.sh b/e2e/servers/gin/build.sh new file mode 100755 index 000000000..a91cb7f01 --- /dev/null +++ b/e2e/servers/gin/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Building Gin server..." +go build -o gin . +echo "✅ Build completed: gin" + diff --git a/e2e/servers/gin/gin b/e2e/servers/gin/gin new file mode 100755 index 000000000..ff5d101aa Binary files /dev/null and b/e2e/servers/gin/gin differ diff --git a/e2e/servers/gin/go.mod b/e2e/servers/gin/go.mod index 078542b14..74749dd52 100644 --- a/e2e/servers/gin/go.mod +++ b/e2e/servers/gin/go.mod @@ -1,41 +1,83 @@ module github.com/coinbase/x402/e2e/servers/gin -go 1.23.3 +go 1.24.0 + +toolchain go1.24.1 require ( - github.com/coinbase/x402/go v0.0.0-00010101000000-000000000000 - github.com/gin-gonic/gin v1.10.0 + github.com/coinbase/x402/go v0.0.0 + github.com/gin-gonic/gin v1.11.0 github.com/joho/godotenv v1.5.1 ) require ( - github.com/bytedance/sonic v1.13.2 // indirect - github.com/bytedance/sonic/loader v0.2.4 // indirect - github.com/cloudwego/base64x v0.1.5 // indirect - github.com/coinbase/cdp-sdk/go v0.0.0-20250506223104-85d38372d771 // indirect + filippo.io/edwards25519 v1.0.0-rc.1 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/blendle/zapdriver v1.3.1 // indirect + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect - github.com/gin-contrib/sse v1.0.0 // indirect + github.com/gagliardetto/binary v0.8.0 // indirect + github.com/gagliardetto/solana-go v1.14.0 // indirect + github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.26.0 // indirect + github.com/go-playground/validator/v10 v10.27.0 // indirect github.com/goccy/go-json v0.10.5 // indirect - github.com/golang-jwt/jwt/v5 v5.2.2 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/holiman/uint256 v1.3.2 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.55.0 // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.12 // indirect - golang.org/x/arch v0.15.0 // indirect - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/net v0.38.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + go.mongodb.org/mongo-driver v1.12.2 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/ratelimit v0.2.0 // indirect + go.uber.org/zap v1.21.0 // indirect + golang.org/x/arch v0.20.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/time v0.9.0 // indirect + golang.org/x/tools v0.36.0 // indirect + google.golang.org/protobuf v1.36.9 // indirect ) replace github.com/coinbase/x402/go => ../../../go diff --git a/e2e/servers/gin/go.sum b/e2e/servers/gin/go.sum index c185673bf..faaacc203 100644 --- a/e2e/servers/gin/go.sum +++ b/e2e/servers/gin/go.sum @@ -1,99 +1,289 @@ -github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= -github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= -github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= -github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= -github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= -github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= -github.com/coinbase/cdp-sdk/go v0.0.0-20250506223104-85d38372d771 h1:zFdgvx+jMCTkrOUTUD2Xmpk4vSusnpGqE90Gl37+WLQ= -github.com/coinbase/cdp-sdk/go v0.0.0-20250506223104-85d38372d771/go.mod h1:7SCUyseVQvmT158f23xvVghYF7dYxypj0sw+558F+7g= +filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= +github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= +github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= +github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= +github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= +github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= +github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= +github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= +github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/crate-crypto/go-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg= +github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= +github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s= +github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs= +github.com/ethereum/go-ethereum v1.16.7 h1:qeM4TvbrWK0UC0tgkZ7NiRsmBGwsjqc64BHo20U59UQ= +github.com/ethereum/go-ethereum v1.16.7/go.mod h1:Fs6QebQbavneQTYcA39PEKv2+zIjX7rPUZ14DER46wk= +github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= +github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= +github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= -github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E= -github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= -github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= -github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= +github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= +github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= +github.com/gagliardetto/solana-go v1.14.0 h1:3WfAi70jOOjAJ0deFMjdhFYlLXATF4tOQXsDNWJtOLw= +github.com/gagliardetto/solana-go v1.14.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= +github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= +github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= +github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= -github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= +github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= -github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk= +github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= -github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= -golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA= +github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.12.2 h1:gbWY1bJkkmUB9jjZzcdhOL8O85N9H+Vvsf2yFN0RDws= +go.mongodb.org/mongo-driver v1.12.2/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= +go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA= +go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c= +golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/e2e/servers/gin/install.sh b/e2e/servers/gin/install.sh new file mode 100755 index 000000000..76d6fd195 --- /dev/null +++ b/e2e/servers/gin/install.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +echo "Installing Go dependencies for Gin server..." +go mod tidy +echo "✅ Dependencies installed" + diff --git a/e2e/servers/gin/main.go b/e2e/servers/gin/main.go index 98c82cd69..310db6302 100644 --- a/e2e/servers/gin/main.go +++ b/e2e/servers/gin/main.go @@ -2,22 +2,32 @@ package main import ( "fmt" - "math/big" "net/http" "os" "os/signal" "syscall" "time" - "github.com/coinbase/x402/go/pkg/coinbasefacilitator" - x402gin "github.com/coinbase/x402/go/pkg/gin" - "github.com/coinbase/x402/go/pkg/types" - "github.com/gin-gonic/gin" + x402 "github.com/coinbase/x402/go" + "github.com/coinbase/x402/go/extensions/bazaar" + "github.com/coinbase/x402/go/extensions/types" + x402http "github.com/coinbase/x402/go/http" + ginmw "github.com/coinbase/x402/go/http/gin" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + svm "github.com/coinbase/x402/go/mechanisms/svm/exact/server" + ginfw "github.com/gin-gonic/gin" "github.com/joho/godotenv" ) var shutdownRequested bool +/** + * Gin E2E Test Server with x402 v2 Payment Middleware + * + * This server demonstrates how to integrate x402 v2 payment middleware + * with a Gin application for end-to-end testing. + */ + func main() { // Load .env file if it exists if err := godotenv.Load(); err != nil { @@ -25,89 +35,201 @@ func main() { } // Get configuration from environment - useCdpFacilitator := os.Getenv("USE_CDP_FACILITATOR") == "true" - network := os.Getenv("EVM_NETWORK") - if network == "" { - network = "base-sepolia" - } - address := os.Getenv("EVM_ADDRESS") port := os.Getenv("PORT") if port == "" { port = "4021" } - // CDP facilitator configuration - cdpAPIKeyID := os.Getenv("CDP_API_KEY_ID") - cdpAPIKeySecret := os.Getenv("CDP_API_KEY_SECRET") - - if address == "" { - fmt.Println("Error: Missing required environment variable ADDRESS") + evmPayeeAddress := os.Getenv("EVM_PAYEE_ADDRESS") + if evmPayeeAddress == "" { + fmt.Println("❌ EVM_PAYEE_ADDRESS environment variable is required") os.Exit(1) } - // Validate CDP configuration if using CDP facilitator - if useCdpFacilitator && (cdpAPIKeyID == "" || cdpAPIKeySecret == "") { - fmt.Println("Error: CDP facilitator enabled but missing CDP_API_KEY_ID or CDP_API_KEY_SECRET") + svmPayeeAddress := os.Getenv("SVM_PAYEE_ADDRESS") + if svmPayeeAddress == "" { + fmt.Println("❌ SVM_PAYEE_ADDRESS environment variable is required") os.Exit(1) } - // Create facilitator config if using CDP - var facilitatorConfig *types.FacilitatorConfig - if useCdpFacilitator { - facilitatorConfig = coinbasefacilitator.CreateFacilitatorConfig(cdpAPIKeyID, cdpAPIKeySecret) + facilitatorURL := os.Getenv("FACILITATOR_URL") + if facilitatorURL == "" { + fmt.Println("❌ FACILITATOR_URL environment variable is required") + os.Exit(1) } + // Network configurations + evmNetwork := x402.Network("eip155:84532") // Base Sepolia + svmNetwork := x402.Network("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") // Solana Devnet + + fmt.Printf("EVM Payee address: %s\n", evmPayeeAddress) + fmt.Printf("SVM Payee address: %s\n", svmPayeeAddress) + fmt.Printf("Using remote facilitator at: %s\n", facilitatorURL) + // Set Gin to release mode to reduce logs - gin.SetMode(gin.ReleaseMode) - r := gin.New() - r.Use(gin.Recovery()) - - // Protected endpoint that requires payment - r.GET("/protected", - x402gin.PaymentMiddleware( - big.NewFloat(0.001), // $0.001 USD - address, - x402gin.WithFacilitatorConfig(facilitatorConfig), - x402gin.WithDescription("Protected endpoint requiring payment"), - x402gin.WithResource("http://localhost:"+port+"/protected"), - x402gin.WithTestnet(network == "base-sepolia"), - ), - func(c *gin.Context) { - if shutdownRequested { - c.JSON(http.StatusServiceUnavailable, gin.H{ - "error": "Server shutting down", - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Access granted to protected resource", + ginfw.SetMode(ginfw.ReleaseMode) + r := ginfw.New() + r.Use(ginfw.Recovery()) + + // Create HTTP facilitator client + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: facilitatorURL, + }) + + /** + * Configure x402 payment middleware + * + * This middleware protects the /protected endpoint with a $0.001 USDC payment requirement + * on the Base Sepolia testnet with bazaar discovery extension. + */ + // Declare bazaar discovery extension for the GET endpoint + discoveryExtension, err := bazaar.DeclareDiscoveryExtension( + bazaar.MethodGET, + nil, // No query params + nil, // No input schema + "", // No body type (GET method) + &types.OutputConfig{ + Example: map[string]interface{}{ + "message": "Protected endpoint accessed successfully", "timestamp": "2024-01-01T00:00:00Z", - "data": gin.H{ - "resource": "premium_content", - "access_level": "paid", + }, + Schema: types.JSONSchema{ + "properties": map[string]interface{}{ + "message": map[string]interface{}{"type": "string"}, + "timestamp": map[string]interface{}{"type": "string"}, }, - }) + "required": []string{"message", "timestamp"}, + }, }, ) + if err != nil { + fmt.Printf("Warning: Failed to create bazaar extension: %v\n", err) + } - // Health check endpoint - r.GET("/health", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "status": "healthy", - "timestamp": "2024-01-01T00:00:00Z", - "server": "gin", + routes := x402http.RoutesConfig{ + "GET /protected": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.001", + Network: evmNetwork, + Extensions: map[string]interface{}{ + types.BAZAAR: discoveryExtension, + }, + }, + "GET /protected-svm": { + Scheme: "exact", + PayTo: svmPayeeAddress, + Price: "$0.001", + Network: svmNetwork, + Extensions: map[string]interface{}{ + types.BAZAAR: discoveryExtension, + }, + }, + } + + // Apply payment middleware with detailed error logging + r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: evmNetwork, Server: evm.NewExactEvmScheme()}, + {Network: svmNetwork, Server: svm.NewExactSvmScheme()}, + }, + Initialize: true, + Timeout: 30 * time.Second, + ErrorHandler: func(c *ginfw.Context, err error) { + // Log detailed error information for debugging + fmt.Printf("❌ [E2E SERVER ERROR] Payment error occurred\n") + fmt.Printf(" Path: %s\n", c.Request.URL.Path) + fmt.Printf(" Method: %s\n", c.Request.Method) + fmt.Printf(" Error: %v\n", err) + fmt.Printf(" Headers: %v\n", c.Request.Header) + + // Default error response + c.JSON(http.StatusPaymentRequired, ginfw.H{ + "error": err.Error(), + }) + }, + SettlementHandler: func(c *ginfw.Context, settleResp *x402.SettleResponse) { + // Log successful settlement + fmt.Printf("✅ [E2E SERVER SUCCESS] Payment settled\n") + fmt.Printf(" Path: %s\n", c.Request.URL.Path) + fmt.Printf(" Transaction: %s\n", settleResp.Transaction) + fmt.Printf(" Network: %s\n", settleResp.Network) + fmt.Printf(" Payer: %s\n", settleResp.Payer) + }, + })) + + /** + * Protected endpoint - requires payment to access + * + * This endpoint demonstrates a resource protected by x402 payment middleware. + * Clients must provide a valid payment signature to access this endpoint. + */ + r.GET("/protected", func(c *ginfw.Context) { + if shutdownRequested { + c.JSON(http.StatusServiceUnavailable, ginfw.H{ + "error": "Server shutting down", + }) + return + } + + c.JSON(http.StatusOK, ginfw.H{ + "message": "Protected endpoint accessed successfully (EVM)", + "timestamp": time.Now().Format(time.RFC3339), + "network": "eip155:84532", }) }) - // Graceful shutdown endpoint - r.POST("/close", func(c *gin.Context) { + /** + * Protected SVM endpoint - requires payment to access + * + * This endpoint demonstrates a Solana payment protected resource. + * Clients must provide a valid payment signature to access this endpoint. + */ + r.GET("/protected-svm", func(c *ginfw.Context) { + if shutdownRequested { + c.JSON(http.StatusServiceUnavailable, ginfw.H{ + "error": "Server shutting down", + }) + return + } + + c.JSON(http.StatusOK, ginfw.H{ + "message": "Protected endpoint accessed successfully (SVM)", + "timestamp": time.Now().Format(time.RFC3339), + "network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + }) + }) + + /** + * Health check endpoint - no payment required + * + * Used to verify the server is running and responsive. + */ + r.GET("/health", func(c *ginfw.Context) { + c.JSON(http.StatusOK, ginfw.H{ + "status": "ok", + "version": "2.0.0", + "evm_network": string(evmNetwork), + "evm_payee": evmPayeeAddress, + "svm_network": string(svmNetwork), + "svm_payee": svmPayeeAddress, + }) + }) + + /** + * Shutdown endpoint - used by e2e tests + * + * Allows graceful shutdown of the server during testing. + */ + r.POST("/close", func(c *ginfw.Context) { shutdownRequested = true - c.JSON(http.StatusOK, gin.H{ - "message": "Server shutting down gracefully", - "timestamp": "2024-01-01T00:00:00Z", + c.JSON(http.StatusOK, ginfw.H{ + "message": "Server shutting down gracefully", }) + fmt.Println("Received shutdown request") // Schedule server shutdown after response go func() { @@ -126,11 +248,24 @@ func main() { os.Exit(0) }() - fmt.Printf("Starting Gin server on port %s\n", port) - fmt.Printf("Server address: %s\n", address) - fmt.Printf("Network: %s\n", network) - fmt.Printf("Using CDP facilitator: %t\n", useCdpFacilitator) - fmt.Printf("Server listening on port %s\n", port) + // Print startup banner + fmt.Printf(` +╔════════════════════════════════════════════════════════╗ +║ x402 Gin E2E Test Server ║ +╠════════════════════════════════════════════════════════╣ +║ Server: http://localhost:%-29s ║ +║ EVM Network: %-40s ║ +║ EVM Payee: %-40s ║ +║ SVM Network: %-40s ║ +║ SVM Payee: %-40s ║ +║ ║ +║ Endpoints: ║ +║ • GET /protected (requires $0.001 EVM payment) ║ +║ • GET /protected-svm (requires $0.001 SVM payment) ║ +║ • GET /health (no payment required) ║ +║ • POST /close (shutdown server) ║ +╚════════════════════════════════════════════════════════╝ +`, port, evmNetwork, evmPayeeAddress, svmNetwork, svmPayeeAddress) server := &http.Server{ Addr: ":" + port, @@ -142,3 +277,13 @@ func main() { os.Exit(1) } } + +func maskPrivateKey(key string) string { + if key == "" { + return "not configured" + } + if len(key) > 10 { + return key[:10] + "..." + } + return key +} diff --git a/e2e/servers/gin/run.sh b/e2e/servers/gin/run.sh old mode 100644 new mode 100755 index 00637611b..2532f0aff --- a/e2e/servers/gin/run.sh +++ b/e2e/servers/gin/run.sh @@ -1,2 +1,3 @@ #!/bin/bash -go run main.go \ No newline at end of file +go run main.go + diff --git a/e2e/servers/gin/server b/e2e/servers/gin/server new file mode 100755 index 000000000..1e5ced19f Binary files /dev/null and b/e2e/servers/gin/server differ diff --git a/e2e/servers/gin/test.config.json b/e2e/servers/gin/test.config.json index 58acb75c6..d2c1f9335 100644 --- a/e2e/servers/gin/test.config.json +++ b/e2e/servers/gin/test.config.json @@ -2,15 +2,26 @@ "name": "gin", "type": "server", "language": "go", - "description": "Go Gin server with x402 payment middleware", + "x402Version": 2, + "extensions": [ + "bazaar" + ], + "description": "Go Gin server with x402 v2 payment middleware", "endpoints": [ { "path": "/protected", "method": "GET", - "description": "Protected endpoint requiring payment", + "description": "Protected endpoint requiring payment (EVM)", "requiresPayment": true, "protocolFamily": "evm" }, + { + "path": "/protected-svm", + "method": "GET", + "description": "Protected endpoint requiring payment (SVM)", + "requiresPayment": true, + "protocolFamily": "svm" + }, { "path": "/health", "method": "GET", @@ -26,14 +37,11 @@ ], "environment": { "required": [ - "EVM_ADDRESS" - ], - "optional": [ "PORT", - "USE_CDP_FACILITATOR", - "EVM_NETWORK", - "CDP_API_KEY_ID", - "CDP_API_KEY_SECRET" - ] + "EVM_PAYEE_ADDRESS", + "SVM_PAYEE_ADDRESS", + "FACILITATOR_URL" + ], + "optional": [] } } \ No newline at end of file diff --git a/e2e/servers/hono/.env-local b/e2e/servers/hono/.env-local index 9e299111b..043fec0ae 100644 --- a/e2e/servers/hono/.env-local +++ b/e2e/servers/hono/.env-local @@ -1,6 +1,8 @@ FACILITATOR_URL=https://x402.org/facilitator -NETWORK=base-sepolia -ADDRESS= +EVM_NETWORK=base-sepolia +SVM_NETWORK=solana-devnet +EVM_ADDRESS= +SVM_ADDRESS= # required if using the Base mainnet facilitator CDP_API_KEY_ID="Coinbase Developer Platform Key" diff --git a/e2e/servers/hono/README.md b/e2e/servers/hono/README.md index 34cfba848..708dd989d 100644 --- a/e2e/servers/hono/README.md +++ b/e2e/servers/hono/README.md @@ -1,150 +1,170 @@ -# x402-hono Example Server +# E2E Test Server: Express (TypeScript) -This is an example Hono server that demonstrates how to use the `x402-hono` middleware to implement paywall functionality in your API endpoints. +This server demonstrates and tests the x402 Express.js middleware with both EVM and SVM payment protection. -## Prerequisites +## What It Tests -- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) -- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) -- A valid Ethereum address for receiving payments -- Coinbase Developer Platform API Key & Secret (if accepting payments on Base mainnet) --- get them here [https://portal.cdp.coinbase.com/projects](https://portal.cdp.coinbase.com/projects) +### Core Functionality +- ✅ **V2 Protocol** - Modern x402 server middleware +- ✅ **Payment Protection** - Middleware protecting specific routes +- ✅ **Multi-chain Support** - EVM and SVM payment acceptance +- ✅ **Facilitator Integration** - HTTP communication with facilitator +- ✅ **Extension Support** - Bazaar discovery metadata +- ✅ **Settlement Handling** - Payment verification and confirmation -## Setup +### Protected Endpoints +- ✅ `GET /protected` - Requires EVM payment (USDC on Base Sepolia) +- ✅ `GET /protected-svm` - Requires SVM payment (USDC on Solana Devnet) -1. Copy `.env-local` to `.env` and add your Ethereum address to receive payments: +## What It Demonstrates -```bash -cp .env-local .env -``` +### Server Setup -2. Install and build all packages from the typescript examples root: - -```bash -cd ../../ -pnpm install -pnpm build -cd servers/hono -``` +```typescript +import express from "express"; +import { x402Middleware } from "@x402/server/express"; +import { ExactEvmServer } from "@x402/evm"; +import { ExactEvmServer } from "@x402/svm"; + +const app = express(); + +// Define payment requirements for routes +const routes = { + "GET /protected": { + scheme: "exact", + network: "eip155:84532", + payTo: "0xYourAddress", + price: "$0.001", + extensions: { + bazaar: discoveryMetadata + } + }, + "GET /protected-svm": { + scheme: "exact", + network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + payTo: "YourSolanaAddress", + price: "$0.001", + extensions: { + bazaar: discoveryMetadata + } + } +}; + +// Apply x402 middleware with EVM and SVM services +app.use(x402Middleware({ + routes, + facilitatorUrl: "http://localhost:4023", + servers: { + "eip155:84532": new ExactEvmServer(), + "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1": new ExactSvmServer() + } +})); -3. Run the server +// Define protected endpoints +app.get("/protected", (req, res) => { + res.json({ message: "EVM payment successful!" }); +}); -```bash -pnpm install -pnpm dev +app.get("/protected-svm", (req, res) => { + res.json({ message: "SVM payment successful!" }); +}); ``` -## Testing the Server +### Key Concepts Shown -You can test the server using one of the example clients: +1. **Route-Based Configuration** - Payment requirements per route +2. **Multi-Chain Services** - Different services for different networks +3. **Price Parsing** - Dollar amounts converted to token units +4. **Facilitator Client** - HTTP communication with payment processor +5. **Extension Metadata** - Bazaar discovery info embedded in responses +6. **Automatic 402 Responses** - Middleware generates payment requirements -### Using the Fetch Client +## Test Scenarios -```bash -cd ../clients/fetch -# Ensure .env is setup -pnpm install -pnpm dev -``` +This server is tested with: +- **Clients:** TypeScript Fetch, Go HTTP +- **Facilitators:** TypeScript, Go +- **Payment Types:** EVM (Base Sepolia), SVM (Solana Devnet) +- **Protocols:** V2 (primary), V1 (via client negotiation) + +### Request Flow +1. Client makes initial request (no payment) +2. Middleware returns 402 with payment requirements +3. Client creates payment payload +4. Client retries with payment signature +5. Middleware verifies payment via facilitator +6. Middleware returns protected content -### Using the Axios Client +## Running ```bash -cd ../clients/axios -# Ensure .env is setup -pnpm install -pnpm dev +# Via e2e test suite +cd e2e +pnpm test --server=express + +# Direct execution +cd e2e/servers/express +export FACILITATOR_URL="http://localhost:4023" +export EVM_PAYEE_ADDRESS="0x..." +export SVM_PAYEE_ADDRESS="..." +export PORT=4022 +pnpm start ``` -These clients will demonstrate how to: +## Environment Variables -1. Make an initial request to get payment requirements -2. Process the payment requirements -3. Make a second request with the payment token +- `PORT` - HTTP server port (default: 4022) +- `FACILITATOR_URL` - Facilitator endpoint URL +- `EVM_PAYEE_ADDRESS` - Ethereum address to receive payments +- `SVM_PAYEE_ADDRESS` - Solana address to receive payments +- `EVM_NETWORK` - EVM network (default: eip155:84532) +- `SVM_NETWORK` - SVM network (default: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1) -## Example Endpoint +## Response Examples -The server includes a single example endpoint at `/weather` that requires a payment of $0.001 to access. The endpoint returns a simple weather report. +### 402 Payment Required (No Payment Sent) -## Response Format - -### Payment Required (402) +``` +HTTP/1.1 402 Payment Required +PAYMENT-REQUIRED: -```json { - "error": "X-PAYMENT header is required", - "paymentRequirements": { - "scheme": "exact", - "network": "base", - "maxAmountRequired": "1000", - "resource": "http://localhost:4021/weather", - "description": "", - "mimeType": "", - "payTo": "0xYourAddress", - "maxTimeoutSeconds": 60, - "asset": "0x...", - "outputSchema": null, - "extra": null - } + "error": "Payment required", + "x402Version": 2, + "accepts": [...] } ``` -### Successful Response +### 200 Success (Payment Verified) + +``` +HTTP/1.1 200 OK +PAYMENT-RESPONSE: -```ts -// Body -{ - "report": { - "weather": "sunny", - "temperature": 70 - } -} -// Headers { - "X-PAYMENT-RESPONSE": "..." // Encoded response object + "message": "Protected endpoint accessed successfully" } ``` -## Extending the Example +## Package Dependencies -To add more paid endpoints, follow this pattern: +- `@x402/server` - Express middleware +- `@x402/evm` - EVM service +- `@x402/svm` - SVM service +- `@x402/extensions/bazaar` - Discovery extension +- `express` - HTTP server framework -```typescript -// First, configure the payment middleware with your routes -app.use( - paymentMiddleware(payTo, { - // Define your routes and their payment requirements - "/your-endpoint": { - price: "$0.10", - network, - }, - "/premium/*": { - price: { - amount: "100000", - asset: { - address: "0xabc", - decimals: 18, - eip712: { - name: "WETH", - version: "1", - }, - }, - }, - network, - }, - }), -); - -// Then define your routes as normal -app.get("/your-endpoint", c => { - return c.json({ - // Your response data - }); -}); +## Implementation Highlights -app.get("/premium/content", c => { - return c.json({ - content: "This is premium content", - }); -}); -``` +### Middleware Features +- **Automatic 402 Responses** - Generates payment requirements +- **Payment Verification** - Validates via facilitator +- **Settlement Tracking** - Includes payment response headers +- **Extension Support** - Embeds bazaar metadata +- **Error Handling** - Clear error messages for payment failures + +### Service Integration +- **EVM Service** - Handles Base Sepolia USDC payments +- **SVM Service** - Handles Solana Devnet USDC payments +- **Price Conversion** - "$0.001" → token amounts with decimals +- **Asset Resolution** - Automatic USDC contract/mint lookup diff --git a/e2e/servers/hono/build.sh b/e2e/servers/hono/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/servers/hono/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/servers/hono/index.ts b/e2e/servers/hono/index.ts index c4a87ca22..458db9847 100644 --- a/e2e/servers/hono/index.ts +++ b/e2e/servers/hono/index.ts @@ -1,69 +1,206 @@ -import { config } from "dotenv"; -import { Hono } from "hono"; import { serve } from "@hono/node-server"; -import { paymentMiddleware, Network, Resource } from "x402-hono"; -import { facilitator } from "@coinbase/x402"; +import { Hono } from "hono"; +import { paymentMiddleware } from "@x402/hono"; +import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; +import { registerExactEvmScheme } from "@x402/evm/exact/server"; +import { registerExactSvmScheme } from "@x402/svm/exact/server"; +import { bazaarResourceServerExtension, declareDiscoveryExtension } from "@x402/extensions/bazaar"; +import dotenv from "dotenv"; -config(); +dotenv.config(); -const useCdpFacilitator = process.env.USE_CDP_FACILITATOR === 'true'; -const payTo = process.env.EVM_ADDRESS as `0x${string}`; -const network = process.env.EVM_NETWORK as Network; -const port = parseInt(process.env.PORT || '4021'); +/** + * Hono E2E Test Server with x402 Payment Middleware + * + * This server demonstrates how to integrate x402 payment middleware + * with a Hono application for end-to-end testing. + */ -if (!payTo || !network) { - console.error("Missing required environment variables"); +const PORT = process.env.PORT || "4023"; +const EVM_NETWORK = "eip155:84532" as const; +const SVM_NETWORK = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" as `${string}:${string}`; +const EVM_PAYEE_ADDRESS = process.env.EVM_PAYEE_ADDRESS as `0x${string}`; +const SVM_PAYEE_ADDRESS = process.env.SVM_PAYEE_ADDRESS as string; +const facilitatorUrl = process.env.FACILITATOR_URL; + +if (!EVM_PAYEE_ADDRESS) { + console.error("❌ EVM_PAYEE_ADDRESS environment variable is required"); process.exit(1); } +if (!SVM_PAYEE_ADDRESS) { + console.error("❌ SVM_PAYEE_ADDRESS environment variable is required"); + process.exit(1); +} + +if (!facilitatorUrl) { + console.error("❌ FACILITATOR_URL environment variable is required"); + process.exit(1); +} + +// Initialize Hono app const app = new Hono(); -// Apply payment middleware to protected endpoint +// Create HTTP facilitator client +const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl }); + +// Create x402 resource server with builder pattern (cleaner!) +const x402Server = new x402ResourceServer(facilitatorClient); + +// Register server schemes +registerExactEvmScheme(x402Server); +registerExactSvmScheme(x402Server); + +// Register Bazaar discovery extension +x402Server.registerExtension(bazaarResourceServerExtension); + +console.log( + `Facilitator account: ${process.env.EVM_PRIVATE_KEY ? process.env.EVM_PRIVATE_KEY.substring(0, 10) + "..." : "not configured"}`, +); +console.log(`Using remote facilitator at: ${facilitatorUrl}`); + +/** + * Configure x402 payment middleware using builder pattern + * + * This middleware protects endpoints with $0.001 USDC payment requirements + * on Base Sepolia and Solana Devnet with bazaar discovery extension. + */ app.use( + "*", paymentMiddleware( - payTo, { - "/protected": { - price: "$0.001", - network, + // Route-specific payment configuration + "GET /protected": { + accepts: { + payTo: EVM_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: EVM_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, + }, + "GET /protected-svm": { + accepts: { + payTo: SVM_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: SVM_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, }, }, - useCdpFacilitator - ? facilitator - : undefined, + x402Server, // Pass pre-configured server instance ), ); -// Protected endpoint requiring payment -app.get("/protected", c => { +/** + * Protected endpoint - requires payment to access + * + * This endpoint demonstrates a resource protected by x402 payment middleware. + * Clients must provide a valid payment signature to access this endpoint. + */ +app.get("/protected", (c) => { return c.json({ message: "Protected endpoint accessed successfully", - timestamp: new Date().toISOString() + timestamp: new Date().toISOString(), }); }); -// Health check endpoint -app.get("/health", c => { +/** + * Protected SVM endpoint - requires payment to access + * + * This endpoint demonstrates a resource protected by x402 payment middleware for SVM. + * Clients must provide a valid payment signature to access this endpoint. + */ +app.get("/protected-svm", (c) => { return c.json({ - status: "healthy" + message: "Protected endpoint accessed successfully", + timestamp: new Date().toISOString(), }); }); -// Graceful shutdown endpoint -app.post("/close", c => { +/** + * Health check endpoint - no payment required + * + * Used to verify the server is running and responsive. + */ +app.get("/health", (c) => { + return c.json({ + status: "ok", + network: EVM_NETWORK, + payee: EVM_PAYEE_ADDRESS, + version: "2.0.0", + }); +}); + +/** + * Shutdown endpoint - used by e2e tests + * + * Allows graceful shutdown of the server during testing. + */ +app.post("/close", (c) => { console.log("Received shutdown request"); + + // Give time for response to be sent setTimeout(() => { process.exit(0); - }, 1000); + }, 100); - return c.json({ - message: "Shutting down gracefully" - }); + return c.json({ message: "Server shutting down gracefully" }); }); -console.log("Server listening on port", port); - -serve({ +// Start the server +const server = serve({ fetch: app.fetch, - port, + port: parseInt(PORT), }); + +console.log(` +╔════════════════════════════════════════════════════════╗ +║ x402 Hono E2E Test Server ║ +╠════════════════════════════════════════════════════════╣ +║ Server: http://localhost:${PORT} ║ +║ EVM Network: ${EVM_NETWORK} ║ +║ SVM Network: ${SVM_NETWORK} ║ +║ EVM Payee: ${EVM_PAYEE_ADDRESS} ║ +║ SVM Payee: ${SVM_PAYEE_ADDRESS} ║ +║ ║ +║ Endpoints: ║ +║ • GET /protected (requires $0.001 USDC payment) ║ +║ • GET /protected-svm (requires $0.001 USDC payment) ║ +║ • GET /health (no payment required) ║ +║ • POST /close (shutdown server) ║ +╚════════════════════════════════════════════════════════╝ + `); diff --git a/e2e/servers/hono/install.sh b/e2e/servers/hono/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/servers/hono/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/servers/hono/package.json b/e2e/servers/hono/package.json index 4f0cefc63..6c21db7cb 100644 --- a/e2e/servers/hono/package.json +++ b/e2e/servers/hono/package.json @@ -1,5 +1,5 @@ { - "name": "hono-server-example", + "name": "@x402/hono-e2e", "private": true, "type": "module", "scripts": { @@ -10,22 +10,27 @@ "lint:check": "eslint . --ext .ts" }, "dependencies": { - "@hono/node-server": "^1.13.8", - "dotenv": "^16.4.7", - "hono": "^4.7.1", - "x402-hono": "workspace:*" + "@hono/node-server": "^1.14.0", + "@x402/core": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/extensions": "workspace:*", + "@x402/hono": "workspace:*", + "@x402/svm": "workspace:*", + "dotenv": "^16.6.1", + "hono": "^4.7.1" }, "devDependencies": { - "tsup": "^7.2.0", - "tsx": "^4.7.0", - "typescript": "^5.3.0", "@eslint/js": "^9.24.0", - "eslint": "^9.24.0", - "eslint-plugin-jsdoc": "^50.6.9", - "eslint-plugin-prettier": "^5.2.6", + "@types/express": "^5.0.1", "@typescript-eslint/eslint-plugin": "^8.29.1", "@typescript-eslint/parser": "^8.29.1", + "eslint": "^9.24.0", "eslint-plugin-import": "^2.31.0", - "prettier": "3.5.2" + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", + "prettier": "3.5.2", + "tsup": "^7.2.0", + "tsx": "^4.7.0", + "typescript": "^5.3.0" } -} +} \ No newline at end of file diff --git a/e2e/servers/hono/test.config.json b/e2e/servers/hono/test.config.json index 857ef5e87..4b2060b17 100644 --- a/e2e/servers/hono/test.config.json +++ b/e2e/servers/hono/test.config.json @@ -1,7 +1,11 @@ { - "name": "hono", + "name": "express", "type": "server", "language": "typescript", + "x402Version": 2, + "extensions": [ + "bazaar" + ], "endpoints": [ { "path": "/protected", @@ -10,6 +14,13 @@ "requiresPayment": true, "protocolFamily": "evm" }, + { + "path": "/protected-svm", + "method": "GET", + "description": "Protected endpoint requiring payment on SVM network", + "requiresPayment": true, + "protocolFamily": "svm" + }, { "path": "/health", "method": "GET", @@ -26,13 +37,10 @@ "environment": { "required": [ "PORT", - "USE_CDP_FACILITATOR", - "EVM_NETWORK", - "EVM_ADDRESS" + "EVM_PAYEE_ADDRESS", + "SVM_PAYEE_ADDRESS", + "FACILITATOR_URL" ], - "optional": [ - "CDP_API_KEY_ID", - "CDP_API_KEY_SECRET" - ] + "optional": [] } } \ No newline at end of file diff --git a/e2e/servers/next/app/api/protected-proxy/route.ts b/e2e/servers/next/app/api/protected-proxy/route.ts new file mode 100644 index 000000000..739c214d8 --- /dev/null +++ b/e2e/servers/next/app/api/protected-proxy/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from "next/server"; + +/** + * Protected endpoint requiring payment (proxy middleware) + */ +export const runtime = "nodejs"; + +/** + * Protected endpoint requiring payment (proxy middleware) + */ +export async function GET() { + return NextResponse.json({ + message: "Protected endpoint accessed successfully", + timestamp: new Date().toISOString(), + }); +} + diff --git a/e2e/servers/next/app/api/protected-svm-proxy/route.ts b/e2e/servers/next/app/api/protected-svm-proxy/route.ts new file mode 100644 index 000000000..f908c8c63 --- /dev/null +++ b/e2e/servers/next/app/api/protected-svm-proxy/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from "next/server"; + +/** + * Protected SVM endpoint requiring payment (proxy middleware) + */ +export const runtime = "nodejs"; + +/** + * Protected SVM endpoint requiring payment (proxy middleware) + */ +export async function GET() { + return NextResponse.json({ + message: "Protected endpoint accessed successfully", + timestamp: new Date().toISOString(), + }); +} + diff --git a/e2e/servers/next/app/api/protected-svm-withx402/route.ts b/e2e/servers/next/app/api/protected-svm-withx402/route.ts new file mode 100644 index 000000000..57b373619 --- /dev/null +++ b/e2e/servers/next/app/api/protected-svm-withx402/route.ts @@ -0,0 +1,48 @@ +import { NextRequest, NextResponse } from "next/server"; +import { withX402 } from "@x402/next"; +import { declareDiscoveryExtension } from "@x402/extensions/bazaar"; +import { server, SVM_PAYEE_ADDRESS, SVM_NETWORK } from "../../../proxy"; + +/** + * Handler for the protected endpoint + */ +const handler = async (_: NextRequest) => { + return NextResponse.json({ + message: "Protected endpoint accessed successfully (withX402)", + timestamp: new Date().toISOString(), + }); +}; + +/** + * Protected SVM endpoint using withX402 wrapper + */ +export const GET = withX402( + handler, + { + accepts: { + payTo: SVM_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: SVM_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected endpoint accessed successfully (withX402)", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, + }, + server, +); + diff --git a/e2e/servers/next/app/api/protected-withx402/route.ts b/e2e/servers/next/app/api/protected-withx402/route.ts new file mode 100644 index 000000000..a7bbbb2f1 --- /dev/null +++ b/e2e/servers/next/app/api/protected-withx402/route.ts @@ -0,0 +1,49 @@ +import { NextRequest, NextResponse } from "next/server"; +import { withX402 } from "@x402/next"; +import { declareDiscoveryExtension } from "@x402/extensions/bazaar"; +import { server, EVM_PAYEE_ADDRESS, EVM_NETWORK } from "../../../proxy"; + +/** + * Handler for the protected endpoint + */ +const handler = async (_: NextRequest) => { + return NextResponse.json({ + message: "Protected endpoint accessed successfully (withX402)", + timestamp: new Date().toISOString(), + }); +}; + +/** + * Protected EVM endpoint using withX402 wrapper + * + */ +export const GET = withX402( + handler, + { + accepts: { + payTo: EVM_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: EVM_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected endpoint accessed successfully (withX402)", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, + }, + server, +); + diff --git a/e2e/servers/next/build.sh b/e2e/servers/next/build.sh new file mode 100755 index 000000000..f526e2c79 --- /dev/null +++ b/e2e/servers/next/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript build handled by pnpm at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/servers/next/install.sh b/e2e/servers/next/install.sh new file mode 100755 index 000000000..220dd8727 --- /dev/null +++ b/e2e/servers/next/install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# TypeScript dependencies handled by pnpm install at root level +# This file is intentionally empty +exit 0 + diff --git a/e2e/servers/next/next.config.ts b/e2e/servers/next/next.config.ts index 2a7522e59..db0a37275 100644 --- a/e2e/servers/next/next.config.ts +++ b/e2e/servers/next/next.config.ts @@ -1,34 +1,6 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - experimental: { - nodeMiddleware: true, // TEMPORARY: Only needed until Edge runtime support is added - }, - serverExternalPackages: ["@coinbase/cdp-sdk"], - env: { - ADDRESS: process.env.ADDRESS, - USE_CDP_FACILITATOR: process.env.USE_CDP_FACILITATOR, - CDP_API_KEY_ID: process.env.CDP_API_KEY_ID, - CDP_API_KEY_SECRET: process.env.CDP_API_KEY_SECRET, - NETWORK: process.env.NETWORK, - PORT: process.env.PORT, - }, - webpack(config) { - config.module.rules.push({ - test: /\.svg$/, - use: ["@svgr/webpack"], - }); - - // Handle Node.js modules that might not be compatible with Edge Runtime - config.resolve.fallback = { - ...config.resolve.fallback, - crypto: require.resolve("crypto-browserify"), - stream: require.resolve("stream-browserify"), - buffer: require.resolve("buffer"), - }; - - return config; - }, }; export default nextConfig; diff --git a/e2e/servers/next/package.json b/e2e/servers/next/package.json index 63cb15786..44536b2b8 100644 --- a/e2e/servers/next/package.json +++ b/e2e/servers/next/package.json @@ -13,17 +13,19 @@ "lint:check": "eslint . --ext .ts" }, "dependencies": { - "@coinbase/x402": "workspace:*", + "@x402/core": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/extensions": "workspace:*", + "@x402/next": "workspace:*", + "@x402/svm": "workspace:*", "@heroicons/react": "^2.2.0", - "next": "canary", - "react": "19.2.1", - "react-dom": "19.2.1", - "viem": "^2.21.26", - "x402-next": "workspace:*" + "next": "^16.0.7", + "react": "^19.2.1", + "react-dom": "^19.2.1", + "viem": "^2.21.26" }, "devDependencies": { "@eslint/js": "^9.24.0", - "@svgr/webpack": "^8.1.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", @@ -32,7 +34,7 @@ "buffer": "^6.0.3", "crypto-browserify": "^3.12.1", "eslint": "^9.24.0", - "eslint-config-next": "15.1.7", + "eslint-config-next": "16.0.7", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsdoc": "^50.6.9", "eslint-plugin-prettier": "^5.2.6", diff --git a/e2e/servers/next/proxy.ts b/e2e/servers/next/proxy.ts new file mode 100644 index 000000000..e17fa5f7d --- /dev/null +++ b/e2e/servers/next/proxy.ts @@ -0,0 +1,93 @@ +import { paymentProxy } from "@x402/next"; +import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; +import { registerExactEvmScheme } from "@x402/evm/exact/server"; +import { registerExactSvmScheme } from "@x402/svm/exact/server"; +import { bazaarResourceServerExtension, declareDiscoveryExtension } from "@x402/extensions/bazaar"; + +export const EVM_PAYEE_ADDRESS = process.env.EVM_PAYEE_ADDRESS as `0x${string}`; +export const SVM_PAYEE_ADDRESS = process.env.SVM_PAYEE_ADDRESS as string; +export const EVM_NETWORK = "eip155:84532" as const; +export const SVM_NETWORK = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" as `${string}:${string}`; +const facilitatorUrl = process.env.FACILITATOR_URL; + +if (!facilitatorUrl) { + console.error("❌ FACILITATOR_URL environment variable is required"); + process.exit(1); +} + +// Create HTTP facilitator client +const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl }); + +// Create x402 resource server with builder pattern (cleaner!) +export const server = new x402ResourceServer(facilitatorClient); + +// Register server schemes +registerExactEvmScheme(server); +registerExactSvmScheme(server); + +// Register Bazaar discovery extension +server.registerExtension(bazaarResourceServerExtension); + +console.log(`Using remote facilitator at: ${facilitatorUrl}`); + +export const proxy = paymentProxy( + { + "/api/protected-proxy": { + accepts: { + payTo: EVM_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: EVM_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, + }, + "/api/protected-svm-proxy": { + accepts: { + payTo: SVM_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: SVM_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, + }, + }, + server, // Pass pre-configured server instance +); + +// Configure which paths the middleware should run on +export const config = { + matcher: ["/api/protected-proxy", "/api/protected-svm-proxy"], +}; + diff --git a/e2e/servers/next/test.config.json b/e2e/servers/next/test.config.json index 3bb162348..87845ae12 100644 --- a/e2e/servers/next/test.config.json +++ b/e2e/servers/next/test.config.json @@ -2,14 +2,39 @@ "name": "next", "type": "server", "language": "typescript", + "x402Version": 2, + "extensions": [ + "bazaar" + ], "endpoints": [ { - "path": "/api/protected", + "path": "/api/protected-proxy", + "method": "GET", + "description": "Protected endpoint using proxy middleware", + "requiresPayment": true, + "protocolFamily": "evm" + }, + { + "path": "/api/protected-svm-proxy", + "method": "GET", + "description": "Protected endpoint using proxy middleware on SVM", + "requiresPayment": true, + "protocolFamily": "svm" + }, + { + "path": "/api/protected-withx402", "method": "GET", - "description": "Protected API endpoint requiring payment", + "description": "Protected endpoint using withX402 wrapper", "requiresPayment": true, "protocolFamily": "evm" }, + { + "path": "/api/protected-svm-withx402", + "method": "GET", + "description": "Protected endpoint using withX402 wrapper on SVM", + "requiresPayment": true, + "protocolFamily": "svm" + }, { "path": "/api/health", "method": "GET", @@ -26,13 +51,10 @@ "environment": { "required": [ "PORT", - "USE_CDP_FACILITATOR", - "EVM_NETWORK", - "EVM_ADDRESS" + "EVM_PAYEE_ADDRESS", + "SVM_PAYEE_ADDRESS", + "FACILITATOR_URL" ], - "optional": [ - "CDP_API_KEY_ID", - "CDP_API_KEY_SECRET" - ] + "optional": [] } } \ No newline at end of file diff --git a/e2e/servers/next/tsconfig.json b/e2e/servers/next/tsconfig.json index 84ffc5cc8..aa175a3f8 100644 --- a/e2e/servers/next/tsconfig.json +++ b/e2e/servers/next/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "target": "ES2022", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": false, @@ -11,7 +15,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { @@ -19,9 +23,20 @@ } ], "paths": { - "@/*": ["./*"] + "@/*": [ + "./*" + ] } }, - "include": ["types/video.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "types/video.d.ts", + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] } diff --git a/e2e/servers/text-server-protocol.txt b/e2e/servers/text-server-protocol.txt index f76586592..9b6569b0a 100644 --- a/e2e/servers/text-server-protocol.txt +++ b/e2e/servers/text-server-protocol.txt @@ -10,12 +10,22 @@ Servers must declare which protocol family each payment endpoint requires in the - **EVM**: Ethereum Virtual Machine compatible networks (Base, Ethereum, etc.) - **SVM**: Solana Virtual Machine compatible networks (Solana, etc.) +## X402 Version Support +Servers must declare which x402 protocol version they implement using the `x402Version` field: +- **x402Version**: The x402 protocol version implemented by the server (e.g., 1 or 2) + +## Extensions Support +Servers may declare which protocol extensions they support using the `extensions` field: +- **extensions**: Array of supported extension names (e.g., ["bazaar"]) + Example configuration: ```json { "name": "my-server", "type": "server", "language": "typescript", + "x402Version": 2, + "extensions": ["bazaar"], "endpoints": [ { "path": "/protected", @@ -39,7 +49,8 @@ Multi-protocol server example: { "name": "universal-server", "type": "server", - "language": "typescript", + "language": "typescript", + "x402Version": 2, "endpoints": [ { "path": "/evm-protected", diff --git a/e2e/setup.sh b/e2e/setup.sh new file mode 100755 index 000000000..05233b9d0 --- /dev/null +++ b/e2e/setup.sh @@ -0,0 +1,196 @@ +#!/bin/bash +set -e + +# Parse command line arguments +INCLUDE_LEGACY=false +VERBOSE=false + +for arg in "$@"; do + case $arg in + --legacy) + INCLUDE_LEGACY=true + shift + ;; + -v|--verbose) + VERBOSE=true + shift + ;; + -h|--help) + echo "Usage: ./setup.sh [options]" + echo "" + echo "Runs install.sh and build.sh for all e2e components" + echo "" + echo "Options:" + echo " --legacy Include legacy (v1) implementations" + echo " -v, --verbose Show detailed output" + echo " -h, --help Show this help message" + echo "" + echo "Examples:" + echo " ./setup.sh # Setup v2 implementations only" + echo " ./setup.sh --legacy # Setup v2 and legacy" + echo " ./setup.sh --legacy -v # Setup with verbose output" + exit 0 + ;; + esac +done + +echo "🚀 X402 E2E Setup" +echo "==================" +echo "" + +if [ "$INCLUDE_LEGACY" = true ]; then + echo "📚 Including legacy (v1) implementations" + echo "" +fi + +# Track results +TOTAL=0 +SUCCESS=0 +FAILED=0 +FAILED_COMPONENTS=() + +# Function to setup a component +setup_component() { + local dir=$1 + local name=$(basename "$dir") + local type=$2 + + TOTAL=$((TOTAL + 1)) + + echo "" + echo "📦 $type: $name" + + local component_success=true + + # Run install.sh if it exists + if [ -f "$dir/install.sh" ]; then + if [ "$VERBOSE" = true ]; then + if (cd "$dir" && bash install.sh); then + echo " ✅ Install completed" + else + echo " ❌ Install failed" + component_success=false + fi + else + if (cd "$dir" && bash install.sh) > /dev/null 2>&1; then + echo " ✅ Install completed" + else + echo " ❌ Install failed" + echo " 💡 Run with -v for detailed output" + component_success=false + fi + fi + fi + + # Run build.sh if it exists + if [ -f "$dir/build.sh" ]; then + if [ "$VERBOSE" = true ]; then + if (cd "$dir" && bash build.sh); then + echo " ✅ Build completed" + else + echo " ❌ Build failed" + component_success=false + fi + else + if (cd "$dir" && bash build.sh) > /dev/null 2>&1; then + echo " ✅ Build completed" + else + echo " ❌ Build failed" + echo " 💡 Run with -v for detailed output" + component_success=false + fi + fi + fi + + if [ "$component_success" = true ]; then + SUCCESS=$((SUCCESS + 1)) + else + FAILED=$((FAILED + 1)) + FAILED_COMPONENTS+=("$type/$name") + fi +} + +# Function to process directory (with optional recursion for nested structures) +process_directory() { + local base_dir=$1 + local type=$2 + local recurse_into=${3:-""} + + if [ ! -d "$base_dir" ]; then + return + fi + + for dir in "$base_dir"/*; do + if [ -d "$dir" ] && [ ! "$(basename "$dir")" = "node_modules" ]; then + local basename=$(basename "$dir") + + # Handle special nested directories (external-proxies, local) + if [ "$basename" = "$recurse_into" ] || [ "$basename" = "local" ]; then + # Recurse into nested directory + process_directory "$dir" "$type" "" + continue + fi + + # Check if component has install.sh or build.sh + if [ -f "$dir/install.sh" ] || [ -f "$dir/build.sh" ]; then + setup_component "$dir" "$type" + fi + fi + done +} + +echo "=======================================================" +echo "Starting Setup Process" +echo "=======================================================" + +# Setup servers +process_directory "servers" "server" + +# Setup clients +process_directory "clients" "client" + +# Setup facilitators (including external-proxies and local subdirectories) +process_directory "facilitators" "facilitator" "external-proxies" + +# Setup legacy if requested +if [ "$INCLUDE_LEGACY" = true ]; then + process_directory "legacy/servers" "server" + process_directory "legacy/clients" "client" + process_directory "legacy/facilitators" "facilitator" +fi + +# Print summary +echo "" +echo "" +echo "═══════════════════════════════════════════════════════" +echo " Setup Summary" +echo "═══════════════════════════════════════════════════════" +echo "✅ Successful: $SUCCESS" +echo "❌ Failed: $FAILED" +echo "📈 Total: $TOTAL" + +if [ $FAILED -gt 0 ]; then + echo "" + echo "❌ FAILED COMPONENTS:" + for component in "${FAILED_COMPONENTS[@]}"; do + echo " • $component" + done + echo "" + echo "═══════════════════════════════════════════════════════" + echo "❌ Setup completed with errors" + echo "═══════════════════════════════════════════════════════" + echo "" + exit 1 +else + echo "" + echo "═══════════════════════════════════════════════════════" + echo "✅ All setup tasks completed successfully!" + echo "═══════════════════════════════════════════════════════" + echo "" + echo "💡 You can now run: pnpm test" + if [ "$INCLUDE_LEGACY" = false ]; then + echo " Or with legacy: pnpm test --legacy" + fi + echo "" +fi + diff --git a/e2e/src/cli/args.ts b/e2e/src/cli/args.ts new file mode 100644 index 000000000..a59bb57f8 --- /dev/null +++ b/e2e/src/cli/args.ts @@ -0,0 +1,119 @@ +import { TestFilters } from './filters'; + +/** + * Parse command-line arguments + * Used primarily for CI/GitHub workflows + */ +export interface ParsedArgs { + mode: 'interactive' | 'programmatic'; + verbose: boolean; + logFile?: string; + filters: TestFilters; + showHelp: boolean; + minimize: boolean; +} + +export function parseArgs(): ParsedArgs { + const args = process.argv.slice(2); + + // Help flag + if (args.includes('-h') || args.includes('--help')) { + return { + mode: 'interactive', + verbose: false, + filters: {}, + showHelp: true, + minimize: false + }; + } + + // Check if any filter args present -> programmatic mode + const hasFilterArgs = args.some(arg => + arg.startsWith('--facilitators=') || + arg.startsWith('--servers=') || + arg.startsWith('--clients=') || + arg.startsWith('--extensions=') || + arg.startsWith('--versions=') || + arg.startsWith('--families=') + ); + + const mode: 'interactive' | 'programmatic' = hasFilterArgs ? 'programmatic' : 'interactive'; + + // Parse verbose + const verbose = args.includes('-v') || args.includes('--verbose'); + + // Parse log file + const logFile = args.find(arg => arg.startsWith('--log-file='))?.split('=')[1]; + + // Parse minimize flag + const minimize = args.includes('--min'); + + // Parse filters (comma-separated lists) + const facilitators = parseListArg(args, '--facilitators'); + const servers = parseListArg(args, '--servers'); + const clients = parseListArg(args, '--clients'); + const extensions = parseListArg(args, '--extensions'); + const versions = parseListArg(args, '--versions')?.map(v => parseInt(v)); + const families = parseListArg(args, '--families'); + + return { + mode, + verbose, + logFile, + filters: { + facilitators, + servers, + clients, + extensions, + versions, + protocolFamilies: families, + }, + showHelp: false, + minimize + }; +} + +function parseListArg(args: string[], argName: string): string[] | undefined { + const arg = args.find(a => a.startsWith(`${argName}=`)); + if (!arg) return undefined; + const value = arg.split('=')[1]; + return value.split(',').map(v => v.trim()).filter(v => v.length > 0); +} + +export function printHelp(): void { + console.log('Usage: pnpm test [options]'); + console.log(''); + console.log('Interactive Mode (default):'); + console.log(' pnpm test Launch interactive prompt mode'); + console.log(' pnpm test -v Interactive with verbose logging'); + console.log(''); + console.log('Programmatic Mode (for CI/workflows):'); + console.log(' --facilitators= Comma-separated facilitator names'); + console.log(' --servers= Comma-separated server names'); + console.log(' --clients= Comma-separated client names'); + console.log(' --extensions= Comma-separated extensions (e.g., bazaar)'); + console.log(' --versions= Comma-separated version numbers (e.g., 1,2)'); + console.log(' --families= Comma-separated protocol families (e.g., evm,svm)'); + console.log(''); + console.log('Options:'); + console.log(' -v, --verbose Enable verbose logging'); + console.log(' --log-file= Save verbose output to file'); + console.log(' --min Minimize tests (coverage-based skipping)'); + console.log(' -h, --help Show this help message'); + console.log(''); + console.log('Examples:'); + console.log(' pnpm test # Interactive mode'); + console.log(' pnpm test -v # Interactive with verbose'); + console.log(' pnpm test --min # Minimize tests'); + console.log(' pnpm test --facilitators=go --servers=express # Programmatic'); + console.log(' pnpm test --facilitators=go,typescript \\'); + console.log(' --servers=legacy-express \\'); + console.log(' --clients=go-http \\'); + console.log(' --extensions=bazaar -v # Full example'); + console.log(' pnpm test --min --facilitators=go,typescript \\'); + console.log(' --extensions=bazaar -v # Minimized with filters'); + console.log(''); + console.log('Note: Extensions control test output visibility, not scenario filtering'); + console.log(''); +} + diff --git a/e2e/src/cli/filters.ts b/e2e/src/cli/filters.ts new file mode 100644 index 000000000..6d800971f --- /dev/null +++ b/e2e/src/cli/filters.ts @@ -0,0 +1,101 @@ +import { TestScenario } from '../types'; + +export interface TestFilters { + facilitators?: string[]; + servers?: string[]; + clients?: string[]; + extensions?: string[]; // For test output control (doesn't filter scenarios) + versions?: number[]; + protocolFamilies?: string[]; +} + +/** + * Filter scenarios based on user selections + * NOTE: Extensions are NOT used for filtering - they only control test output + */ +export function filterScenarios( + scenarios: TestScenario[], + filters: TestFilters +): TestScenario[] { + return scenarios.filter(scenario => { + // Facilitator filter + if (filters.facilitators && filters.facilitators.length > 0) { + const facilitatorName = scenario.facilitator?.name; + if (!facilitatorName || !filters.facilitators.includes(facilitatorName)) { + return false; + } + } + + // Server filter + if (filters.servers && filters.servers.length > 0) { + if (!filters.servers.includes(scenario.server.name)) { + return false; + } + } + + // Client filter + if (filters.clients && filters.clients.length > 0) { + if (!filters.clients.includes(scenario.client.name)) { + return false; + } + } + + // Version filter + if (filters.versions && filters.versions.length > 0) { + const serverVersion = scenario.server.config.x402Version; + if (!serverVersion || !filters.versions.includes(serverVersion)) { + return false; + } + } + + // Protocol family filter + if (filters.protocolFamilies && filters.protocolFamilies.length > 0) { + if (!filters.protocolFamilies.includes(scenario.protocolFamily)) { + return false; + } + } + + // NOTE: Extensions filter NOT applied - it only controls test output visibility + // Extensions are stored separately and passed to test execution logic + + return true; + }); +} + +/** + * Check if extension-related test output should be shown + */ +export function shouldShowExtensionOutput( + extensionName: string, + selectedExtensions?: string[] +): boolean { + // If no extensions selected, don't show extension output + if (!selectedExtensions || selectedExtensions.length === 0) { + return false; + } + + return selectedExtensions.includes(extensionName); +} + +/** + * Extract unique versions from scenarios + */ +export function getUniqueVersions(scenarios: TestScenario[]): number[] { + const versions = new Set(); + scenarios.forEach(s => { + if (s.server.config.x402Version) { + versions.add(s.server.config.x402Version); + } + }); + return Array.from(versions).sort(); +} + +/** + * Extract unique protocol families from scenarios + */ +export function getUniqueProtocolFamilies(scenarios: TestScenario[]): string[] { + const families = new Set(); + scenarios.forEach(s => families.add(s.protocolFamily)); + return Array.from(families).sort(); +} + diff --git a/e2e/src/cli/interactive.ts b/e2e/src/cli/interactive.ts new file mode 100644 index 000000000..261236622 --- /dev/null +++ b/e2e/src/cli/interactive.ts @@ -0,0 +1,322 @@ +import prompts from 'prompts'; +import { DiscoveredClient, DiscoveredServer, DiscoveredFacilitator, TestScenario } from '../types'; +import { TestFilters, getUniqueVersions, getUniqueProtocolFamilies } from './filters'; +import { log } from '../logger'; + +export interface InteractiveSelections extends TestFilters { + // All fields from TestFilters +} + +/** + * Run interactive mode to select test scenarios + * + * @param allClients - All discovered clients + * @param allServers - All discovered servers + * @param allFacilitators - All discovered facilitators + * @param allScenarios - All test scenarios + * @param minimize - If true (--min flag), default all items selected. If false, default none selected. + */ +export async function runInteractiveMode( + allClients: DiscoveredClient[], + allServers: DiscoveredServer[], + allFacilitators: DiscoveredFacilitator[], + allScenarios: TestScenario[], + minimize: boolean = false +): Promise { + + log('\n🎯 Interactive Mode'); + log('==================\n'); + + // Question 1: Select facilitators (multi-select) + // Sort facilitators: regular ones first, external ones at the bottom + const regularFacilitators = allFacilitators.filter(f => !f.isExternal); + const externalFacilitators = allFacilitators.filter(f => f.isExternal); + + const facilitatorChoices: any[] = []; + + // Add regular facilitators + regularFacilitators.forEach(f => { + facilitatorChoices.push({ + title: `${f.name} (${formatVersions(f.config.x402Versions)}) [${f.config.protocolFamilies?.join(', ') || ''}]${f.config.extensions ? ' {' + f.config.extensions.join(', ') + '}' : ''}`, + value: f.name, + selected: minimize // With --min: all selected. Without --min: none selected + }); + }); + + // Add external facilitators section if any exist + if (externalFacilitators.length > 0) { + // Add separator/header for external facilitators + facilitatorChoices.push({ + title: '────────── External ──────────', + value: '__external_separator__', + disabled: true + }); + + externalFacilitators.forEach(f => { + facilitatorChoices.push({ + title: `${f.name} (${formatVersions(f.config.x402Versions)}) [${f.config.protocolFamilies?.join(', ') || ''}]${f.config.extensions ? ' {' + f.config.extensions.join(', ') + '}' : ''}`, + value: f.name, + selected: false // External facilitators are never selected by default + }); + }); + } + + const facilitatorsResponse = await prompts({ + type: 'multiselect', + name: 'facilitators', + message: 'Select facilitators', + choices: facilitatorChoices, + min: 1, + hint: 'Space to select, Enter to confirm', + instructions: false + }); + + if (!facilitatorsResponse.facilitators || facilitatorsResponse.facilitators.length === 0) { + return null; // User cancelled + } + + // Question 2: Select servers (multi-select) + const serverChoices = allServers.map(s => { + const families = Array.from(new Set(s.config.endpoints?.map(e => e.protocolFamily).filter(Boolean))) || []; + const extInfo = s.config.extensions ? ' {' + s.config.extensions.join(', ') + '}' : ''; + return { + title: `${s.name} (v${s.config.x402Version}) [${families.join(', ')}]${extInfo}`, + value: s.name, + selected: minimize // With --min: all selected. Without --min: none selected + }; + }); + + const serversResponse = await prompts({ + type: 'multiselect', + name: 'servers', + message: 'Select servers', + choices: serverChoices, + min: 1, + hint: 'Space to select, Enter to confirm', + instructions: false + }); + + if (!serversResponse.servers || serversResponse.servers.length === 0) { + return null; + } + + // Question 3: Select clients (multi-select) + const clientChoices = allClients.map(c => ({ + title: `${c.name} (${formatVersions(c.config.x402Versions)}) [${c.config.protocolFamilies?.join(', ') || ''}]`, + value: c.name, + selected: minimize // With --min: all selected. Without --min: none selected + })); + + const clientsResponse = await prompts({ + type: 'multiselect', + name: 'clients', + message: 'Select clients', + choices: clientChoices, + min: 1, + hint: 'Space to select, Enter to confirm', + instructions: false + }); + + if (!clientsResponse.clients || clientsResponse.clients.length === 0) { + return null; + } + + // Question 4: Select extensions (ALWAYS shown if any available, determines test output visibility) + log('\n🔍 Detecting available extensions from selections...\n'); + + const availableExtensions = getAvailableExtensions( + facilitatorsResponse.facilitators, + serversResponse.servers, + allFacilitators, + allServers + ); + + let selectedExtensions: string[] | undefined; + + if (availableExtensions.length > 0) { + const extensionChoices = availableExtensions.map(ext => ({ + title: `${ext.name} (${ext.description})`, + value: ext.name, + selected: true // Default all selected + })); + + const extensionsResponse = await prompts({ + type: 'multiselect', + name: 'extensions', + message: 'Select extensions (controls test output visibility)', + choices: extensionChoices, + hint: 'Space to select, Enter to confirm or skip', + instructions: false + }); + + selectedExtensions = extensionsResponse.extensions; + + if (selectedExtensions && selectedExtensions.length > 0) { + log(`ℹ️ Extensions enabled: ${selectedExtensions.join(', ')}`); + log(' (Extension validation output will be shown)\n'); + } + } + + // Now analyze what scenarios would be generated from these selections + log('🔍 Analyzing remaining scenarios...\n'); + + const preliminaryScenarios = filterScenariosBySelections( + allScenarios, + { + facilitators: facilitatorsResponse.facilitators, + servers: serversResponse.servers, + clients: clientsResponse.clients + } + ); + + // Question 5 (CONDITIONAL): Select versions IF multiple versions exist in remaining scenarios + const availableVersions = getUniqueVersions(preliminaryScenarios); + let selectedVersions: number[] | undefined; + + if (availableVersions.length > 1) { + const versionChoices = availableVersions.map(v => { + const count = preliminaryScenarios.filter(s => s.server.config.x402Version === v).length; + return { + title: `v${v} (${count} scenarios)`, + value: v, + selected: true + }; + }); + + const versionsResponse = await prompts({ + type: 'multiselect', + name: 'versions', + message: 'Select x402 versions', + choices: versionChoices, + min: 1, + hint: 'Space to select, Enter to confirm', + instructions: false + }); + + if (!versionsResponse.versions || versionsResponse.versions.length === 0) { + return null; + } + + selectedVersions = versionsResponse.versions; + } else if (availableVersions.length === 1) { + // Auto-select if only one version + selectedVersions = availableVersions; + } + + // Question 6 (CONDITIONAL): Select protocol families IF multiple families exist + const availableFamilies = getUniqueProtocolFamilies(preliminaryScenarios); + let selectedFamilies: string[] | undefined; + + if (availableFamilies.length > 1) { + const familyChoices = availableFamilies.map(f => { + const count = preliminaryScenarios.filter(s => s.protocolFamily === f).length; + return { + title: `${f.toUpperCase()} (${count} scenarios)`, + value: f, + selected: true + }; + }); + + const familiesResponse = await prompts({ + type: 'multiselect', + name: 'families', + message: 'Select protocol families', + choices: familyChoices, + min: 1, + hint: 'Space to select, Enter to confirm', + instructions: false + }); + + if (!familiesResponse.families || familiesResponse.families.length === 0) { + return null; + } + + selectedFamilies = familiesResponse.families; + } else if (availableFamilies.length === 1) { + // Auto-select if only one family + selectedFamilies = availableFamilies; + } + + return { + facilitators: facilitatorsResponse.facilitators, + servers: serversResponse.servers, + clients: clientsResponse.clients, + extensions: selectedExtensions, + versions: selectedVersions, + protocolFamilies: selectedFamilies, + }; +} + +/** + * Get available extensions from selected facilitators and servers + */ +function getAvailableExtensions( + facilitatorNames: string[], + serverNames: string[], + allFacilitators: DiscoveredFacilitator[], + allServers: DiscoveredServer[] +): Array<{ name: string; description: string }> { + const extensions = new Set(); + const extensionInfo: Record = { + 'bazaar': 'Discovery extension for resource discovery', + }; + + // Collect from facilitators + facilitatorNames.forEach(name => { + const facilitator = allFacilitators.find(f => f.name === name); + if (facilitator?.config.extensions) { + facilitator.config.extensions.forEach(ext => extensions.add(ext)); + } + }); + + // Collect from servers + serverNames.forEach(name => { + const server = allServers.find(s => s.name === name); + if (server?.config.extensions) { + server.config.extensions.forEach(ext => extensions.add(ext)); + } + }); + + return Array.from(extensions).map(ext => ({ + name: ext, + description: extensionInfo[ext] || ext + })); +} + +/** + * Filter scenarios based on preliminary selections (before version/family filtering) + */ +function filterScenariosBySelections( + scenarios: TestScenario[], + selections: { facilitators: string[]; servers: string[]; clients: string[] } +): TestScenario[] { + return scenarios.filter(scenario => { + // Facilitator filter + const facilitatorName = scenario.facilitator?.name; + if (!facilitatorName || !selections.facilitators.includes(facilitatorName)) { + return false; + } + + // Server filter + if (!selections.servers.includes(scenario.server.name)) { + return false; + } + + // Client filter + if (!selections.clients.includes(scenario.client.name)) { + return false; + } + + return true; + }); +} + +/** + * Format version array for display + */ +function formatVersions(versions?: number[]): string { + if (!versions || versions.length === 0) return 'v?'; + if (versions.length === 1) return `v${versions[0]}`; + return `v${versions.join(', v')}`; +} + diff --git a/e2e/src/clients/generic-client.ts b/e2e/src/clients/generic-client.ts index 07cb553ed..6a5b050c2 100644 --- a/e2e/src/clients/generic-client.ts +++ b/e2e/src/clients/generic-client.ts @@ -23,7 +23,7 @@ export class GenericClientProxy extends BaseProxy implements ClientProxy { EVM_PRIVATE_KEY: config.evmPrivateKey, SVM_PRIVATE_KEY: config.svmPrivateKey, RESOURCE_SERVER_URL: config.serverUrl, - ENDPOINT_PATH: config.endpointPath + ENDPOINT_PATH: config.endpointPath, } }; diff --git a/e2e/src/discovery.ts b/e2e/src/discovery.ts index 0fcecdf8b..728309c8c 100644 --- a/e2e/src/discovery.ts +++ b/e2e/src/discovery.ts @@ -2,29 +2,33 @@ import { readdirSync, readFileSync, existsSync } from 'fs'; import { join } from 'path'; import { GenericServerProxy } from './servers/generic-server'; import { GenericClientProxy } from './clients/generic-client'; +import { GenericFacilitatorProxy } from './facilitators/generic-facilitator'; import { log, verboseLog, errorLog } from './logger'; import { TestConfig, DiscoveredServer, DiscoveredClient, + DiscoveredFacilitator, TestScenario, ProtocolFamily } from './types'; -const facilitatorNetworkCombos = [ - { useCdpFacilitator: false, network: 'base-sepolia', protocolFamily: 'evm' as ProtocolFamily }, - { useCdpFacilitator: true, network: 'base-sepolia', protocolFamily: 'evm' as ProtocolFamily }, - { useCdpFacilitator: true, network: 'base', protocolFamily: 'evm' as ProtocolFamily }, - { useCdpFacilitator: false, network: 'solana-devnet', protocolFamily: 'svm' as ProtocolFamily }, - { useCdpFacilitator: true, network: 'solana-devnet', protocolFamily: 'svm' as ProtocolFamily }, - { useCdpFacilitator: true, network: 'solana', protocolFamily: 'svm' as ProtocolFamily } -]; +// Will be populated with discovered facilitators +let facilitatorNetworkCombos: Array<{ + useCdpFacilitator: boolean; + network: string; + protocolFamily: ProtocolFamily; + x402Version: number; + facilitatorName?: string; +}> = []; export class TestDiscovery { private baseDir: string; + private includeLegacy: boolean; - constructor(baseDir: string = '.') { + constructor(baseDir: string = '.', includeLegacy: boolean = false) { this.baseDir = baseDir; + this.includeLegacy = includeLegacy; } getFacilitatorNetworkCombos(): typeof facilitatorNetworkCombos { @@ -56,12 +60,29 @@ export class TestDiscovery { * Discover all servers in the servers directory */ discoverServers(): DiscoveredServer[] { + const servers: DiscoveredServer[] = []; + + // Discover servers from main servers directory const serversDir = join(this.baseDir, 'servers'); - if (!existsSync(serversDir)) { - return []; + if (existsSync(serversDir)) { + this.discoverServersInDirectory(serversDir, servers); } - const servers: DiscoveredServer[] = []; + // Discover servers from legacy directory if flag is set + if (this.includeLegacy) { + const legacyServersDir = join(this.baseDir, 'legacy', 'servers'); + if (existsSync(legacyServersDir)) { + this.discoverServersInDirectory(legacyServersDir, servers, 'legacy-'); + } + } + + return servers; + } + + /** + * Helper method to discover servers in a specific directory + */ + private discoverServersInDirectory(serversDir: string, servers: DiscoveredServer[], namePrefix: string = ''): void { let serverDirs = readdirSync(serversDir, { withFileTypes: true }) .filter(dirent => dirent.isDirectory()) .map(dirent => dirent.name); @@ -77,31 +98,117 @@ export class TestDiscovery { if (config.type === 'server') { servers.push({ - name: serverName, + name: namePrefix + serverName, directory: serverDir, config, proxy: new GenericServerProxy(serverDir) }); } } catch (error) { - errorLog(`Failed to load config for server ${serverName}: ${error}`); + errorLog(`Failed to load config for server ${namePrefix}${serverName}: ${error}`); } } } - - return servers; } /** * Discover all clients in the clients directory */ discoverClients(): DiscoveredClient[] { + const clients: DiscoveredClient[] = []; + + // Discover clients from main clients directory const clientsDir = join(this.baseDir, 'clients'); - if (!existsSync(clientsDir)) { - return []; + if (existsSync(clientsDir)) { + this.discoverClientsInDirectory(clientsDir, clients); } - const clients: DiscoveredClient[] = []; + // Discover clients from legacy directory if flag is set + if (this.includeLegacy) { + const legacyClientsDir = join(this.baseDir, 'legacy', 'clients'); + if (existsSync(legacyClientsDir)) { + this.discoverClientsInDirectory(legacyClientsDir, clients, 'legacy-'); + } + } + + return clients; + } + + /** + * Discover all facilitators in the facilitators directory + */ + discoverFacilitators(): DiscoveredFacilitator[] { + const facilitators: DiscoveredFacilitator[] = []; + + // Discover facilitators from main facilitators directory + const facilitatorsDir = join(this.baseDir, 'facilitators'); + if (existsSync(facilitatorsDir)) { + this.discoverFacilitatorsInDirectory(facilitatorsDir, facilitators); + } + + // Discover facilitators from legacy directory if flag is set + if (this.includeLegacy) { + const legacyFacilitatorsDir = join(this.baseDir, 'legacy', 'facilitators'); + if (existsSync(legacyFacilitatorsDir)) { + this.discoverFacilitatorsInDirectory(legacyFacilitatorsDir, facilitators, 'legacy-'); + } + } + + return facilitators; + } + + /** + * Helper method to discover facilitators in a specific directory + */ + private discoverFacilitatorsInDirectory(facilitatorsDir: string, facilitators: DiscoveredFacilitator[], namePrefix: string = '', isExternal: boolean = false): void { + let facilitatorDirs = readdirSync(facilitatorsDir, { withFileTypes: true }) + .filter(dirent => dirent.isDirectory()) + .map(dirent => dirent.name); + + for (const facilitatorName of facilitatorDirs) { + const facilitatorDir = join(facilitatorsDir, facilitatorName); + + // Special case: external-proxies is a nested directory of more facilitators + if (facilitatorName === 'external-proxies') { + verboseLog(` 🔍 Found external-proxies directory, discovering nested facilitators...`); + this.discoverFacilitatorsInDirectory(facilitatorDir, facilitators, '', true); + continue; + } + + // Special case: local is a nested directory of more facilitators (inherits isExternal from parent) + if (facilitatorName === 'local') { + verboseLog(` 🔍 Found local directory, discovering nested facilitators...`); + this.discoverFacilitatorsInDirectory(facilitatorDir, facilitators, '', isExternal); + continue; + } + + const configPath = join(facilitatorDir, 'test.config.json'); + + if (existsSync(configPath)) { + try { + const configContent = readFileSync(configPath, 'utf-8'); + const config: TestConfig = JSON.parse(configContent); + + if (config.type === 'facilitator') { + facilitators.push({ + name: namePrefix + facilitatorName, + directory: facilitatorDir, + config, + proxy: new GenericFacilitatorProxy(facilitatorDir), + isExternal + }); + } + } catch (error) { + errorLog(`Failed to load config for facilitator ${namePrefix}${facilitatorName}: ${error}`); + } + } + } + } + + /** + * Helper method to discover clients in a specific directory + */ + private discoverClientsInDirectory(clientsDir: string, clients: DiscoveredClient[], namePrefix: string = ''): void { let clientDirs = readdirSync(clientsDir, { withFileTypes: true }) .filter(dirent => dirent.isDirectory()) .map(dirent => dirent.name); @@ -117,19 +224,62 @@ export class TestDiscovery { if (config.type === 'client') { clients.push({ - name: clientName, + name: namePrefix + clientName, directory: clientDir, config, proxy: new GenericClientProxy(clientDir) }); } } catch (error) { - errorLog(`Failed to load config for client ${clientName}: ${error}`); + errorLog(`Failed to load config for client ${namePrefix}${clientName}: ${error}`); } } } + } - return clients; + /** + * Build facilitator network combos from discovered facilitators + */ + private buildFacilitatorNetworkCombos(facilitators: DiscoveredFacilitator[]): void { + facilitatorNetworkCombos = []; + + for (const facilitator of facilitators) { + const protocolFamilies = facilitator.config.protocolFamilies || ['evm']; + const x402Versions = facilitator.config.x402Versions || [2]; + + for (const protocolFamily of protocolFamilies) { + for (const x402Version of x402Versions) { + // Add network combos based on protocol family + if (protocolFamily === 'evm') { + facilitatorNetworkCombos.push({ + useCdpFacilitator: false, + network: 'eip155:84532', + protocolFamily: protocolFamily as ProtocolFamily, + x402Version, + facilitatorName: facilitator.name + }); + } else if (protocolFamily === 'svm') { + facilitatorNetworkCombos.push({ + useCdpFacilitator: false, + network: 'solana:devnet', + protocolFamily: protocolFamily as ProtocolFamily, + x402Version, + facilitatorName: facilitator.name + }); + } + } + } + } + + // If no facilitators found, add a default combo for backward compatibility + if (facilitatorNetworkCombos.length === 0) { + facilitatorNetworkCombos.push({ + useCdpFacilitator: false, + network: 'eip155:84532', + protocolFamily: 'evm', + x402Version: 2 + }); + } } /** @@ -138,13 +288,39 @@ export class TestDiscovery { generateTestScenarios(): TestScenario[] { const servers = this.discoverServers(); const clients = this.discoverClients(); + const facilitators = this.discoverFacilitators(); + + // Build facilitator network combos from discovered facilitators + this.buildFacilitatorNetworkCombos(facilitators); + const scenarios: TestScenario[] = []; for (const client of clients) { // Default to EVM if no protocol families specified for backward compatibility const clientProtocolFamilies = client.config.protocolFamilies || ['evm']; + // Get client's supported x402 versions (default to [1] for backward compatibility) + const clientVersions = client.config.x402Versions; + if (!clientVersions) { + errorLog(` ⚠️ Skipping ${client.name}: No x402 versions specified`); + continue; + } + for (const server of servers) { + // Get server's x402 version (default to 1 for backward compatibility) + const serverVersion = server.config.x402Version; + if (!serverVersion) { + errorLog(` ⚠️ Skipping ${server.name}: No x402 version specified`); + continue; + } + + // Check if client and server have compatible versions + if (!clientVersions.includes(serverVersion)) { + // Skip this client-server pair if versions don't overlap + verboseLog(` ⚠️ Skipping ${client.name} ↔ ${server.name}: Version mismatch (client supports [${clientVersions.join(', ')}], server implements ${serverVersion})`); + continue; + } + // Only test endpoints that require payment const testableEndpoints = server.config.endpoints?.filter(endpoint => { // Only include endpoints that require payment @@ -161,9 +337,21 @@ export class TestDiscovery { const combosForProtocol = this.getFacilitatorNetworkCombosForProtocol(endpointProtocolFamily); for (const combo of combosForProtocol) { + // Skip if facilitator doesn't support the server's x402 version + if (combo.x402Version !== serverVersion) { + verboseLog(` ⚠️ Skipping facilitator ${combo.facilitatorName} for ${server.name}: Version mismatch (facilitator supports v${combo.x402Version}, server implements v${serverVersion})`); + continue; + } + + // Find matching facilitator if specified + const matchingFacilitator = combo.facilitatorName + ? facilitators.find(f => f.name === combo.facilitatorName) + : undefined; + scenarios.push({ client, server, + facilitator: matchingFacilitator, endpoint, protocolFamily: endpointProtocolFamily, facilitatorNetworkCombo: { @@ -186,25 +374,54 @@ export class TestDiscovery { printDiscoverySummary(): void { const servers = this.discoverServers(); const clients = this.discoverClients(); + const facilitators = this.discoverFacilitators(); + + // Build combos to get accurate scenario count + this.buildFacilitatorNetworkCombos(facilitators); const scenarios = this.generateTestScenarios(); log('🔍 Test Discovery Summary'); log('========================'); + if (this.includeLegacy) { + log('🔄 Legacy mode enabled - including legacy implementations'); + } log(`📡 Servers found: ${servers.length}`); servers.forEach(server => { const paidEndpoints = server.config.endpoints?.filter(e => e.requiresPayment).length || 0; const protocolFamilies = new Set( server.config.endpoints?.filter(e => e.requiresPayment).map(e => e.protocolFamily || 'evm') || ['evm'] ); - log(` - ${server.name} (${server.config.language}) - ${paidEndpoints} x402 endpoints [${Array.from(protocolFamilies).join(', ')}]`); + const version = server.config.x402Version || 1; + log(` - ${server.name} (${server.config.language}) v${version} - ${paidEndpoints} x402 endpoints [${Array.from(protocolFamilies).join(', ')}]`); }); log(`📱 Clients found: ${clients.length}`); clients.forEach(client => { const protocolFamilies = client.config.protocolFamilies || ['evm']; - log(` - ${client.name} (${client.config.language}) [${protocolFamilies.join(', ')}]`); + const versions = client.config.x402Versions || [1]; + log(` - ${client.name} (${client.config.language}) v[${versions.join(', ')}] [${protocolFamilies.join(', ')}]`); }); + log(`🏛️ Facilitators found: ${facilitators.length}`); + + const regularFacilitators = facilitators.filter(f => !f.isExternal); + const externalFacilitators = facilitators.filter(f => f.isExternal); + + regularFacilitators.forEach(facilitator => { + const protocolFamilies = facilitator.config.protocolFamilies || ['evm']; + const versions = facilitator.config.x402Versions || [2]; + log(` - ${facilitator.name} (${facilitator.config.language}) v[${versions.join(', ')}] [${protocolFamilies.join(', ')}]`); + }); + + if (externalFacilitators.length > 0) { + log(` External:`); + externalFacilitators.forEach(facilitator => { + const protocolFamilies = facilitator.config.protocolFamilies || ['evm']; + const versions = facilitator.config.x402Versions || [2]; + log(` - ${facilitator.name} (${facilitator.config.language}) v[${versions.join(', ')}] [${protocolFamilies.join(', ')}]`); + }); + } + log(`🔧 Facilitator/Network combos: ${this.getFacilitatorNetworkCombos().length}`); // Show protocol family breakdown diff --git a/e2e/src/facilitators/generic-facilitator.ts b/e2e/src/facilitators/generic-facilitator.ts new file mode 100644 index 000000000..77f090b29 --- /dev/null +++ b/e2e/src/facilitators/generic-facilitator.ts @@ -0,0 +1,333 @@ +import { BaseProxy, RunConfig } from '../proxy-base'; +import { verboseLog, errorLog } from '../logger'; + +export interface VerifyRequest { + x402Version: number; + paymentPayload: any; + paymentRequirements: any; +} + +export interface VerifyResponse { + isValid: boolean; + invalidReason?: string; + payer?: string; +} + +export interface SettleRequest { + x402Version: number; + paymentPayload: any; + paymentRequirements: any; +} + +export interface SettleResponse { + success: boolean; + transaction?: string; + errorReason?: string; + network?: string; + payer?: string; +} + +export interface SupportedResponse { + kinds: Array<{ + x402Version: number; + scheme: string; + network: string; + extra?: Record; + }>; + extensions: any[]; +} + +export interface HealthResponse { + status: string; +} + +export interface FacilitatorResult { + success: boolean; + data?: T; + error?: string; + statusCode?: number; +} + +export interface FacilitatorConfig { + port: number; + evmPrivateKey?: string; + svmPrivateKey?: string; + evmNetwork?: string; + svmNetwork?: string; +} + +export interface FacilitatorProxy { + start(config: FacilitatorConfig): Promise; + stop(): Promise; + verify(request: VerifyRequest): Promise>; + settle(request: SettleRequest): Promise>; + getSupported(): Promise>; + health(): Promise>; + getUrl(): string; +} + +export class GenericFacilitatorProxy extends BaseProxy implements FacilitatorProxy { + private port: number = 4022; + private healthEndpoint: string = '/health'; + private closeEndpoint: string = '/close'; + + constructor(directory: string) { + // Facilitators should log when ready + super(directory, 'Facilitator listening'); + this.loadEndpoints(); + } + + private loadEndpoints(): void { + try { + const { readFileSync, existsSync } = require('fs'); + const { join } = require('path'); + const configPath = join(this.directory, 'test.config.json'); + + if (existsSync(configPath)) { + const configContent = readFileSync(configPath, 'utf-8'); + const config = JSON.parse(configContent); + + // Load health endpoint if specified + const healthEndpoint = config.endpoints?.find((endpoint: any) => endpoint.health); + if (healthEndpoint) { + this.healthEndpoint = healthEndpoint.path; + } + + // Load close endpoint if specified + const closeEndpoint = config.endpoints?.find((endpoint: any) => endpoint.close); + if (closeEndpoint) { + this.closeEndpoint = closeEndpoint.path; + } + } + } catch (error) { + // Fallback to defaults if config loading fails + errorLog(`Failed to load endpoints from config for ${this.directory}, using defaults`); + } + } + + async start(config: FacilitatorConfig): Promise { + this.port = config.port; + + const baseEnv: Record = { + PORT: config.port.toString(), + EVM_PRIVATE_KEY: config.evmPrivateKey || '', + SVM_PRIVATE_KEY: config.svmPrivateKey || '', + EVM_NETWORK: config.evmNetwork || 'eip155:84532', + SVM_NETWORK: config.svmNetwork || 'solana:devnet', + EVM_RPC_URL: process.env.BASE_SEPOLIA_RPC_URL || process.env.EVM_RPC_URL || '', + }; + + // Pass through any additional environment variables required by the facilitator + // This supports external facilitators that may need custom env vars (e.g., CDP_API_KEY_ID) + const facilitatorConfig = this.loadConfig(); + if (facilitatorConfig?.environment?.required) { + for (const envVar of facilitatorConfig.environment.required) { + if (process.env[envVar] && !baseEnv[envVar]) { + baseEnv[envVar] = process.env[envVar]!; + } + } + } + if (facilitatorConfig?.environment?.optional) { + for (const envVar of facilitatorConfig.environment.optional) { + if (process.env[envVar] && !baseEnv[envVar]) { + baseEnv[envVar] = process.env[envVar]!; + } + } + } + + const runConfig: RunConfig = { + port: config.port, + env: baseEnv + }; + + await this.startProcess(runConfig); + } + + private loadConfig(): any { + try { + const { readFileSync, existsSync } = require('fs'); + const { join } = require('path'); + const configPath = join(this.directory, 'test.config.json'); + + if (existsSync(configPath)) { + const configContent = readFileSync(configPath, 'utf-8'); + return JSON.parse(configContent); + } + } catch (error) { + errorLog(`Failed to load config from ${this.directory}: ${error}`); + } + return null; + } + + async verify(request: VerifyRequest): Promise> { + try { + const response = await fetch(`http://localhost:${this.port}/verify`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(request), + }); + + if (!response.ok) { + return { + success: false, + error: `Verify failed: ${response.status} ${response.statusText}`, + statusCode: response.status + }; + } + + const data = await response.json(); + return { + success: true, + data: data as VerifyResponse, + statusCode: response.status + }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error) + }; + } + } + + async settle(request: SettleRequest): Promise> { + try { + const response = await fetch(`http://localhost:${this.port}/settle`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(request), + }); + + if (!response.ok) { + return { + success: false, + error: `Settle failed: ${response.status} ${response.statusText}`, + statusCode: response.status + }; + } + + const data = await response.json(); + return { + success: true, + data: data as SettleResponse, + statusCode: response.status + }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error) + }; + } + } + + async getSupported(): Promise> { + try { + const response = await fetch(`http://localhost:${this.port}/supported`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + return { + success: false, + error: `Get supported failed: ${response.status} ${response.statusText}`, + statusCode: response.status + }; + } + + const data = await response.json(); + return { + success: true, + data: data as SupportedResponse, + statusCode: response.status + }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error) + }; + } + } + + async health(): Promise> { + try { + const response = await fetch(`http://localhost:${this.port}${this.healthEndpoint}`); + + if (!response.ok) { + return { + success: false, + error: `Health check failed: ${response.status} ${response.statusText}`, + statusCode: response.status + }; + } + + const data = await response.json(); + return { + success: true, + data: data as HealthResponse, + statusCode: response.status + }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error) + }; + } + } + + async close(): Promise> { + try { + const response = await fetch(`http://localhost:${this.port}${this.closeEndpoint}`, { + method: 'POST' + }); + + if (!response.ok) { + return { + success: false, + error: `Close failed: ${response.status} ${response.statusText}`, + statusCode: response.status + }; + } + + const data = await response.json(); + return { + success: true, + data: data as { message: string }, + statusCode: response.status + }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error) + }; + } + } + + async stop(): Promise { + if (this.process) { + try { + // Try graceful shutdown via POST /close + const closeResult = await this.close(); + if (closeResult.success) { + // Wait a bit for graceful shutdown + await new Promise(resolve => setTimeout(resolve, 2000)); + } else { + verboseLog('Graceful shutdown failed, using force kill'); + } + } catch (error) { + verboseLog('Graceful shutdown failed, using force kill'); + } + } + + await this.stopProcess(); + } + + getUrl(): string { + return `http://localhost:${this.port}`; + } +} diff --git a/e2e/src/networks/networks.ts b/e2e/src/networks/networks.ts new file mode 100644 index 000000000..b8075e3a1 --- /dev/null +++ b/e2e/src/networks/networks.ts @@ -0,0 +1,41 @@ +type Network = { + name: string; + caip2: `${string}:${string}`; + v1Name?: string; + rpcUrl: string; +} + +export const NETWORKS = [ + { + name: 'Base Sepolia', + caip2: 'eip155:84532', + v1Name: 'base-sepolia', + rpcUrl: process.env.BASE_SEPOLIA_RPC_URL || 'https://sepolia.base.org', + }, + { + name: "Solana Devnet", + caip2: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', + v1Name: 'solana-devnet', + rpcUrl: process.env.SOLANA_DEVNET_RPC_URL || 'https://api.devnet.solana.com', + }, + { + name: 'Base', + caip2: 'eip155:8453', + v1Name: 'base', + rpcUrl: process.env.BASE_RPC_URL || 'https://mainnet.base.org', + }, + { + name: "Solana", + caip2: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', + v1Name: 'solana-devnet', + rpcUrl: process.env.SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com', + }, +] satisfies Network[]; + +export const getNetwork = (network: string): Network | undefined => { + let result = NETWORKS.find(n => n.caip2 === network); + if (!result) { + result = NETWORKS.find(n => n.v1Name === network); + } + return result; +} \ No newline at end of file diff --git a/e2e/src/proxy-base.ts b/e2e/src/proxy-base.ts index 7ee1cc73b..b7312e276 100644 --- a/e2e/src/proxy-base.ts +++ b/e2e/src/proxy-base.ts @@ -80,11 +80,13 @@ export abstract class BaseProxy { let output = ''; let stderr = ''; + let resolved = false; this.process.stdout?.on('data', (data) => { output += data.toString(); verboseLog(`[${this.directory}] stdout: ${data.toString()}`); - if (output.includes(this.readyLog)) { + if (output.includes(this.readyLog) && !resolved) { + resolved = true; resolve(); } }); @@ -96,19 +98,29 @@ export abstract class BaseProxy { this.process.on('error', (error) => { errorLog(`[${this.directory}] Error: ${error}`); - reject(error); + if (!resolved) { + resolved = true; + reject(error); + } }); this.process.on('exit', (code) => { - // Only log non-zero exit codes for debugging - if (code !== 0) { + // If process exits during startup with non-zero code, reject + if (code !== 0 && !resolved) { + resolved = true; + const errorMsg = `Process exited with code ${code} during startup`; + errorLog(`[${this.directory}] ${errorMsg}`); + reject(new Error(errorMsg)); + } else if (code !== 0) { + // Already resolved, just log for debugging errorLog(`[${this.directory}] Process exited with code ${code}`); } }); // Timeout after 30 seconds setTimeout(() => { - if (this.process && !this.process.killed) { + if (this.process && !this.process.killed && !resolved) { + resolved = true; resolve(); } }, 30000); @@ -173,20 +185,28 @@ export abstract class BaseProxy { }); childProcess.on('close', (code: number | null) => { - if (code === 0) { - try { - // Find JSON result in stdout - const lines = stdout.split('\n'); - const jsonLine = lines.find(line => line.trim().startsWith('{')); - if (jsonLine) { - const result = JSON.parse(jsonLine); + // Try to find JSON in stdout regardless of exit code + try { + const lines = stdout.split('\n'); + const jsonLine = lines.find(line => line.trim().startsWith('{')); + if (jsonLine) { + const result = JSON.parse(jsonLine); + if (code === 0) { resolve({ success: true, data: result, exitCode: code }); } else { - resolve({ success: false, error: 'No JSON result found', exitCode: code }); + // Non-zero exit but we have JSON error details + const errorMsg = result.error || `Process exited with code ${code}`; + resolve({ success: false, error: errorMsg, exitCode: code || undefined }); } - } catch (error) { - resolve({ success: false, error: `Failed to parse result: ${error}`, exitCode: code }); + return; } + } catch (error) { + // Failed to parse JSON, fall through to default error handling + } + + // No JSON found or parse failed + if (code === 0) { + resolve({ success: false, error: 'No JSON result found', exitCode: code }); } else { resolve({ success: false, error: stderr || `Process exited with code ${code}`, exitCode: code || undefined }); } diff --git a/e2e/src/sampling.ts b/e2e/src/sampling.ts new file mode 100644 index 000000000..8a4d88259 --- /dev/null +++ b/e2e/src/sampling.ts @@ -0,0 +1,193 @@ +import { TestScenario } from './types'; +import { log, verboseLog } from './logger'; + +/** + * Coverage tracker for minimizing test runs + * + * Tracks which components (client, server, facilitator) have been tested + * with which protocol families and versions to skip redundant tests. + */ +export class CoverageTracker { + private clientsCovered = new Set(); + private serversCovered = new Set(); + private facilitatorsCovered = new Set(); + private endpointsCovered = new Set(); + + /** + * Generate a coverage key for a component + * Format: "component-name-protocolFamily-vVersion" + * + * Args: + * componentName: Name of the component + * protocolFamily: Protocol family (e.g., 'evm', 'svm') + * version: x402 version number + * + * Returns: + * Coverage key string + */ + private getCoverageKey(componentName: string, protocolFamily: string, version: number): string { + return `${componentName}-${protocolFamily}-v${version}`; + } + + /** + * Generate a coverage key for an endpoint + * Format: "server-name-endpoint-path-protocolFamily-vVersion" + * + * This ensures each unique endpoint on a server is tested separately. + */ + private getEndpointCoverageKey(serverName: string, endpointPath: string, protocolFamily: string, version: number): string { + return `${serverName}-${endpointPath}-${protocolFamily}-v${version}`; + } + + /** + * Check if a scenario provides new coverage + * + * A scenario provides new coverage if ANY of its components haven't been + * tested with this protocol family and version combination. + * + * Args: + * scenario: Test scenario to evaluate + * + * Returns: + * true if scenario provides new coverage, false if all components already covered + */ + isNewCoverage(scenario: TestScenario): boolean { + const version = scenario.server.config.x402Version; + const protocolFamily = scenario.protocolFamily; + + const clientKey = this.getCoverageKey( + scenario.client.name, + protocolFamily, + version + ); + const serverKey = this.getCoverageKey( + scenario.server.name, + protocolFamily, + version + ); + const facilitatorKey = this.getCoverageKey( + scenario.facilitator?.name || 'default', + protocolFamily, + version + ); + const endpointKey = this.getEndpointCoverageKey( + scenario.server.name, + scenario.endpoint.path, + protocolFamily, + version + ); + + // Check if ANY component hasn't been covered yet + const clientNew = !this.clientsCovered.has(clientKey); + const serverNew = !this.serversCovered.has(serverKey); + const facilitatorNew = !this.facilitatorsCovered.has(facilitatorKey); + const endpointNew = !this.endpointsCovered.has(endpointKey); + + const isNew = clientNew || serverNew || facilitatorNew || endpointNew; + + if (isNew) { + verboseLog(` 📊 New coverage: ${clientNew ? `client(${clientKey})` : ''} ${serverNew ? `server(${serverKey})` : ''} ${facilitatorNew ? `facilitator(${facilitatorKey})` : ''} ${endpointNew ? `endpoint(${endpointKey})` : ''}`); + } + + return isNew; + } + + /** + * Mark a scenario's components as covered + * + * Args: + * scenario: Test scenario to mark as covered + */ + markCovered(scenario: TestScenario): void { + const version = scenario.server.config.x402Version; + const protocolFamily = scenario.protocolFamily; + + const clientKey = this.getCoverageKey( + scenario.client.name, + protocolFamily, + version + ); + const serverKey = this.getCoverageKey( + scenario.server.name, + protocolFamily, + version + ); + const facilitatorKey = this.getCoverageKey( + scenario.facilitator?.name || 'default', + protocolFamily, + version + ); + const endpointKey = this.getEndpointCoverageKey( + scenario.server.name, + scenario.endpoint.path, + protocolFamily, + version + ); + + this.clientsCovered.add(clientKey); + this.serversCovered.add(serverKey); + this.facilitatorsCovered.add(facilitatorKey); + this.endpointsCovered.add(endpointKey); + } + + /** + * Get coverage statistics + * + * Returns: + * Object containing coverage counts for each component type + */ + getStats(): { clients: number; servers: number; facilitators: number; endpoints: number } { + return { + clients: this.clientsCovered.size, + servers: this.serversCovered.size, + facilitators: this.facilitatorsCovered.size, + endpoints: this.endpointsCovered.size, + }; + } +} + +/** + * Filter scenarios based on coverage to minimize test runs + * + * Only includes scenarios that provide new coverage (i.e., test a component + * with a protocol family and version combination that hasn't been tested yet). + * + * Args: + * scenarios: All test scenarios to filter + * + * Returns: + * Filtered list of scenarios that provide new coverage + */ +export function minimizeScenarios(scenarios: TestScenario[]): TestScenario[] { + const tracker = new CoverageTracker(); + const minimized: TestScenario[] = []; + + for (const scenario of scenarios) { + if (tracker.isNewCoverage(scenario)) { + minimized.push(scenario); + tracker.markCovered(scenario); + } else { + verboseLog(` ⏭️ Skipping (covered): ${scenario.client.name} → ${scenario.server.name} → ${scenario.endpoint.path} [${scenario.facilitator?.name || 'default'}] (${scenario.protocolFamily}-v${scenario.server.config.x402Version})`); + } + } + + const stats = tracker.getStats(); + const reductionPercent = ((1 - minimized.length / scenarios.length) * 100).toFixed(1); + + log(''); + log('📊 Coverage-Based Minimization'); + log('=============================='); + log(`Total scenarios: ${scenarios.length}`); + log(`Selected scenarios: ${minimized.length} (${reductionPercent}% reduction)`); + log(`Skipped scenarios: ${scenarios.length - minimized.length}`); + log(''); + log('Coverage achieved:'); + log(` • Clients: ${stats.clients} unique combinations`); + log(` • Servers: ${stats.servers} unique combinations`); + log(` • Facilitators: ${stats.facilitators} unique combinations`); + log(` • Endpoints: ${stats.endpoints} unique combinations`); + log(''); + + return minimized; +} + diff --git a/e2e/src/servers/generic-server.ts b/e2e/src/servers/generic-server.ts index a4d665343..d4a47f587 100644 --- a/e2e/src/servers/generic-server.ts +++ b/e2e/src/servers/generic-server.ts @@ -1,6 +1,33 @@ import { BaseProxy, RunConfig } from '../proxy-base'; -import { ServerProxy, ServerConfig } from '../types'; +import { ServerProxy } from '../types'; import { verboseLog, errorLog } from '../logger'; +import { getNetwork } from '../networks/networks'; + +/** + * Translates v2 CAIP-2 network format to v1 simple format for legacy servers + * + * @param network - Network in CAIP-2 format (e.g., "eip155:84532") + * @returns Network in v1 format (e.g., "base-sepolia") + */ +function translateNetworkForV1(network: string): string { + const networkMap: Record = { + 'eip155:84532': 'base-sepolia', + 'eip155:8453': 'base', + 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1': 'solana-devnet', + 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp': 'solana-mainnet', + }; + + return networkMap[network] || network; +} + +interface ServerConfig { + port: number; + evmPayTo: string; + svmPayTo: string; + evmNetwork: string; + svmNetwork: string; + facilitatorUrl?: string; +} export interface ProtectedResponse { message: string; @@ -67,17 +94,38 @@ export class GenericServerProxy extends BaseProxy implements ServerProxy { async start(config: ServerConfig): Promise { this.port = config.port; + // Check if this is a v1 (legacy) server based on directory name + const isV1Server = this.directory.includes('legacy/'); + + verboseLog(` 📂 Server directory: ${this.directory}, isV1: ${isV1Server}`); + + // Translate networks to v1 format for legacy servers using getNetwork helper + let evmNetwork = config.evmNetwork; + let svmNetwork = config.svmNetwork; + + if (isV1Server) { + // Use getNetwork to look up and get v1 name + const evmNetworkInfo = getNetwork(config.evmNetwork); + const svmNetworkInfo = getNetwork(config.svmNetwork); + + evmNetwork = evmNetworkInfo?.v1Name || translateNetworkForV1(config.evmNetwork); + svmNetwork = svmNetworkInfo?.v1Name || translateNetworkForV1(config.svmNetwork); + + verboseLog(` 🔄 Translating networks for v1 server: ${config.evmNetwork} → ${evmNetwork}, ${config.svmNetwork} → ${svmNetwork}`); + } + const runConfig: RunConfig = { port: config.port, env: { - USE_CDP_FACILITATOR: config.useCdpFacilitator.toString(), - CDP_API_KEY_ID: process.env.CDP_API_KEY_ID || '', - CDP_API_KEY_SECRET: process.env.CDP_API_KEY_SECRET || '', - EVM_NETWORK: config.evmNetwork, - EVM_ADDRESS: config.evmPayTo, - SVM_NETWORK: config.svmNetwork, - SVM_ADDRESS: config.svmPayTo, - PORT: config.port.toString() + EVM_NETWORK: evmNetwork, + EVM_PAYEE_ADDRESS: config.evmPayTo, + SVM_NETWORK: svmNetwork, + SVM_PAYEE_ADDRESS: config.svmPayTo, + PORT: config.port.toString(), + EVM_RPC_URL: getNetwork(config.evmNetwork)?.rpcUrl || '', + + // Use facilitator URL if provided + FACILITATOR_URL: config.facilitatorUrl || '', } }; diff --git a/e2e/src/types.ts b/e2e/src/types.ts index 4f10f0e04..14fde0c60 100644 --- a/e2e/src/types.ts +++ b/e2e/src/types.ts @@ -8,20 +8,20 @@ export interface ClientResult { error?: string; } +export interface ClientConfig { + evmPrivateKey: string; + svmPrivateKey: string; + serverUrl: string; + endpointPath: string; +} + export interface ServerConfig { port: number; - useCdpFacilitator: boolean; evmPayTo: string; svmPayTo: string; evmNetwork: string; svmNetwork: string; -} - -export interface ClientConfig { - evmPrivateKey: string; - svmPrivateKey: string; - serverUrl: string; - endpointPath: string; + facilitatorUrl?: string; } export interface ServerProxy { @@ -50,9 +50,12 @@ export interface TestEndpoint { export interface TestConfig { name: string; - type: 'server' | 'client'; + type: 'server' | 'client' | 'facilitator'; language: string; protocolFamilies?: ProtocolFamily[]; + x402Version?: number; // For servers - single version they implement + x402Versions?: number[]; // For clients and facilitators - array of versions they support + extensions?: string[]; // Protocol extensions supported (e.g., ["bazaar"]) endpoints?: TestEndpoint[]; supportedMethods?: string[]; capabilities?: { @@ -79,14 +82,30 @@ export interface DiscoveredClient { proxy: ClientProxy; } +export interface FacilitatorProxy { + start(config: any): Promise; + stop(): Promise; + getUrl(): string; +} + +export interface DiscoveredFacilitator { + name: string; + directory: string; + config: TestConfig; + proxy: FacilitatorProxy; + isExternal?: boolean; +} + export interface TestScenario { client: DiscoveredClient; server: DiscoveredServer; + facilitator?: DiscoveredFacilitator; endpoint: TestEndpoint; protocolFamily: ProtocolFamily; facilitatorNetworkCombo: { useCdpFacilitator: boolean; network: string; + facilitatorUrl?: string; }; } diff --git a/e2e/templates/server-ts/.env-local b/e2e/templates/server-ts/.env-local new file mode 100644 index 000000000..043fec0ae --- /dev/null +++ b/e2e/templates/server-ts/.env-local @@ -0,0 +1,9 @@ +FACILITATOR_URL=https://x402.org/facilitator +EVM_NETWORK=base-sepolia +SVM_NETWORK=solana-devnet +EVM_ADDRESS= +SVM_ADDRESS= + +# required if using the Base mainnet facilitator +CDP_API_KEY_ID="Coinbase Developer Platform Key" +CDP_API_KEY_SECRET="Coinbase Developer Platform Key Secret" \ No newline at end of file diff --git a/examples/typescript/fullstack/mainnet/.prettierignore b/e2e/templates/server-ts/.prettierignore similarity index 100% rename from examples/typescript/fullstack/mainnet/.prettierignore rename to e2e/templates/server-ts/.prettierignore diff --git a/examples/typescript/fullstack/mainnet/.prettierrc b/e2e/templates/server-ts/.prettierrc similarity index 100% rename from examples/typescript/fullstack/mainnet/.prettierrc rename to e2e/templates/server-ts/.prettierrc diff --git a/e2e/templates/server-ts/README.md b/e2e/templates/server-ts/README.md new file mode 100644 index 000000000..dd4b92b86 --- /dev/null +++ b/e2e/templates/server-ts/README.md @@ -0,0 +1,105 @@ +# x402 E2E Test Server + +## Overview + +## Setup + +### Prerequisites + +1. Node.js and pnpm installed +2. Environment variables configured: + ```bash + EVM_PRIVATE_KEY=0x... # Private key for facilitator account + EVM_PAYEE_ADDRESS=0x... # Address to receive payments + PORT=4021 # Optional: server port (defaults to 4021) + ``` + +### Installation + +```bash +pnpm install +``` + +### Running the Server + +```bash +pnpm run start +``` + +Or for development with auto-reload: + +```bash +pnpm run dev +``` + +## Endpoints + +### Protected Endpoint +- **GET /protected** - Requires $0.001 USDC payment on Base Sepolia +- Returns success message with timestamp when payment is valid + +### Utility Endpoints +- **GET /health** - Health check (no payment required) +- **POST /close** - Gracefully shutdown server (for testing) + +## Architecture + +### Components + +1. **`index.ts`** - Main server file with Express app and route configuration +2. **`facilitator.ts`** - Local facilitator setup for payment processing + +### Payment Flow + +1. Client requests protected endpoint +2. Server returns 402 Payment Required with payment instructions +3. Client creates and signs payment +4. Client retries request with payment signature +5. Server verifies payment via facilitator +6. If valid, server processes request and settles payment +7. Server returns response with settlement confirmation + +## Testing + +This server is used by the e2e test suite to verify x402 client implementations. The local facilitator allows testing without relying on external services. + +### Running E2E Tests + +From the project root: + +```bash +pnpm run test:e2e +``` + +## Production Considerations + +For production use: + +1. Replace the local facilitator with a remote facilitator service +2. Configure appropriate payment amounts and networks +3. Add proper error handling and logging +4. Implement rate limiting and security measures +5. Use environment-specific configuration + +## Troubleshooting + +### Common Issues + +1. **"EVM_PRIVATE_KEY environment variable is required"** + - Ensure `.env` file exists with required variables + - Check that dotenv is loading correctly + +2. **"Server already running on port"** + - Check for existing processes: `lsof -i :4021` + - Kill existing process or use different port + +3. **Payment verification fails** + - Verify private key matches the expected account + - Check network configuration matches client + - Ensure sufficient balance for gas fees + +## Related Documentation + +- [x402 Protocol Specification](../../../specs/x402-specification.md) +- [Express Middleware Package](../../../typescript/packages/http/express/README.md) +- [E2E Test Suite](../../README.md) \ No newline at end of file diff --git a/e2e/templates/server-ts/eslint.config.js b/e2e/templates/server-ts/eslint.config.js new file mode 100644 index 000000000..e2fde7b3b --- /dev/null +++ b/e2e/templates/server-ts/eslint.config.js @@ -0,0 +1,73 @@ +import js from "@eslint/js"; +import ts from "@typescript-eslint/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; +import prettier from "eslint-plugin-prettier"; +import jsdoc from "eslint-plugin-jsdoc"; +import importPlugin from "eslint-plugin-import"; + +export default [ + { + ignores: ["dist/**", "node_modules/**"], + }, + { + files: ["**/*.ts"], + languageOptions: { + parser: tsParser, + sourceType: "module", + ecmaVersion: 2020, + globals: { + process: "readonly", + __dirname: "readonly", + module: "readonly", + require: "readonly", + Buffer: "readonly", + console: "readonly", + exports: "readonly", + setTimeout: "readonly", + clearTimeout: "readonly", + setInterval: "readonly", + clearInterval: "readonly", + }, + }, + plugins: { + "@typescript-eslint": ts, + prettier: prettier, + jsdoc: jsdoc, + import: importPlugin, + }, + rules: { + ...ts.configs.recommended.rules, + "import/first": "error", + "prettier/prettier": "error", + "@typescript-eslint/member-ordering": "error", + "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_$" }], + "jsdoc/tag-lines": ["error", "any", { startLines: 1 }], + "jsdoc/check-alignment": "error", + "jsdoc/no-undefined-types": "off", + "jsdoc/check-param-names": "error", + "jsdoc/check-tag-names": "error", + "jsdoc/check-types": "error", + "jsdoc/implements-on-classes": "error", + "jsdoc/require-description": "error", + "jsdoc/require-jsdoc": [ + "error", + { + require: { + FunctionDeclaration: true, + MethodDefinition: true, + ClassDeclaration: true, + ArrowFunctionExpression: false, + FunctionExpression: false, + }, + }, + ], + "jsdoc/require-param": "error", + "jsdoc/require-param-description": "error", + "jsdoc/require-param-type": "off", + "jsdoc/require-returns": "error", + "jsdoc/require-returns-description": "error", + "jsdoc/require-returns-type": "off", + "jsdoc/require-hyphen-before-param-description": ["error", "always"], + }, + }, +]; diff --git a/e2e/templates/server-ts/index.ts b/e2e/templates/server-ts/index.ts new file mode 100644 index 000000000..76725de8f --- /dev/null +++ b/e2e/templates/server-ts/index.ts @@ -0,0 +1,39 @@ +/** + * Express E2E Test Server with x402 Payment Middleware + * + * This server demonstrates how to integrate x402 payment middleware + * with an Express application for end-to-end testing. + */ + +/** + * Environment variables + * - PORT: Port to listen on + * - EVM_PAYEE_ADDRESS: EVM address to receive payments + * - SVM_PAYEE_ADDRESS: SVM address to receive payments + * - FACILITATOR_URL: URL of the facilitator + */ + +/** + * Implement Server app + * - Create server + * - Register x402 middleware + * - Configure payment required endpoints in middleware + * - Implement payment required endpoints + * - Implement health check endpoint + * - Implement shutdown endpoint + * + * On startup, log the server details and endpoints +╔════════════════════════════════════════════════════════╗ +║ x402 E2E Test Server ║ +╠════════════════════════════════════════════════════════╣ +║ Server: http://localhost: ║ +║ Protocol Family: ║ +║ Network: ║ +║ Payee: ║ +║ ║ +║ Endpoints: ║ +║ • GET /protected (requires payment) ║ +║ • GET /health (no payment required) ║ +║ • POST /close (shutdown server) ║ +╚════════════════════════════════════════════════════════╝ + */ diff --git a/e2e/templates/server-ts/package.json b/e2e/templates/server-ts/package.json new file mode 100644 index 000000000..19ffe028f --- /dev/null +++ b/e2e/templates/server-ts/package.json @@ -0,0 +1,29 @@ +{ + "name": "@x402/-e2e", + "private": true, + "type": "module", + "scripts": { + "dev": "tsx index.ts", + "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", + "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", + "lint": "eslint . --ext .ts --fix", + "lint:check": "eslint . --ext .ts" + }, + "dependencies": { + "@x402/core": "workspace:*", + "dotenv": "^16.6.1" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "eslint": "^9.24.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", + "prettier": "3.5.2", + "tsup": "^7.2.0", + "tsx": "^4.7.0", + "typescript": "^5.3.0" + } +} \ No newline at end of file diff --git a/e2e/templates/server-ts/run.sh b/e2e/templates/server-ts/run.sh new file mode 100755 index 000000000..aa2c67d61 --- /dev/null +++ b/e2e/templates/server-ts/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pnpm dev \ No newline at end of file diff --git a/e2e/templates/server-ts/test.config.json b/e2e/templates/server-ts/test.config.json new file mode 100644 index 000000000..a6369ac09 --- /dev/null +++ b/e2e/templates/server-ts/test.config.json @@ -0,0 +1,38 @@ +{ + "name": "express", + "type": "server", + "language": "typescript", + "x402Version": 2, + "extensions": [ + "bazaar" + ], + "endpoints": [ + { + "path": "/protected", + "method": "GET", + "description": "Protected endpoint requiring payment", + "requiresPayment": true, + "protocolFamily": "evm" + }, + { + "path": "/health", + "method": "GET", + "description": "Health check endpoint", + "health": true + }, + { + "path": "/close", + "method": "POST", + "description": "Graceful shutdown endpoint", + "close": true + } + ], + "environment": { + "required": [ + "PORT", + "EVM_PAYEE_ADDRESS", + "FACILITATOR_URL" + ], + "optional": [] + } +} \ No newline at end of file diff --git a/e2e/templates/server-ts/tsconfig.json b/e2e/templates/server-ts/tsconfig.json new file mode 100644 index 000000000..78f9479b1 --- /dev/null +++ b/e2e/templates/server-ts/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "strict": true, + "resolveJsonModule": true, + "baseUrl": ".", + "types": ["node"] + }, + "include": ["index.ts"] +} diff --git a/examples/typescript/mcp-embedded-wallet/src/components/DiscoveryModal/DiscoveryModal.module.css b/e2e/templates/server/README.md similarity index 100% rename from examples/typescript/mcp-embedded-wallet/src/components/DiscoveryModal/DiscoveryModal.module.css rename to e2e/templates/server/README.md diff --git a/e2e/templates/server/run.sh b/e2e/templates/server/run.sh new file mode 100644 index 000000000..cbb80942b --- /dev/null +++ b/e2e/templates/server/run.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# Run the server +## e.g. pnpm dev +## go run main.go +## uv run python main.py \ No newline at end of file diff --git a/e2e/templates/server/setup.sh b/e2e/templates/server/setup.sh new file mode 100644 index 000000000..fa5d2310d --- /dev/null +++ b/e2e/templates/server/setup.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# Setup the server +## e.g. pnpm install && pnpm build +## go get -u && go build -v ./... +## uv sync && uv run build \ No newline at end of file diff --git a/e2e/templates/server/test.config.json b/e2e/templates/server/test.config.json new file mode 100644 index 000000000..83c36679e --- /dev/null +++ b/e2e/templates/server/test.config.json @@ -0,0 +1,41 @@ +{ + "name": "", + "type": "server", + "language": "", + "x402Version": "<1/2>", + "extensions": [ + "", + "" + ], + "description": "", + "endpoints": [ + { + "path": "/protected", + "method": "", + "description": "", + "requiresPayment": true, + "protocolFamily": "" + }, + { + "path": "/health", + "method": "GET", + "description": "Health check endpoint", + "health": true + }, + { + "path": "/close", + "method": "POST", + "description": "Graceful shutdown endpoint", + "close": true + } + ], + "environment": { + "required": [ + "PORT", + "EVM_PAYEE_ADDRESS", + "SVM_PAYEE_ADDRESS", + "FACILITATOR_URL" + ], + "optional": [] + } +} \ No newline at end of file diff --git a/e2e/test.ts b/e2e/test.ts index 0feb99fac..d7f6a7f83 100644 --- a/e2e/test.ts +++ b/e2e/test.ts @@ -1,154 +1,238 @@ import { config } from 'dotenv'; import { TestDiscovery } from './src/discovery'; -import { ServerConfig, ClientConfig, ScenarioResult } from './src/types'; +import { ClientConfig, ScenarioResult } from './src/types'; import { config as loggerConfig, log, verboseLog, errorLog, close as closeLogger } from './src/logger'; +import { handleDiscoveryValidation, shouldRunDiscoveryValidation } from './extensions/bazaar'; +import { parseArgs, printHelp } from './src/cli/args'; +import { runInteractiveMode } from './src/cli/interactive'; +import { filterScenarios, TestFilters, shouldShowExtensionOutput } from './src/cli/filters'; +import { minimizeScenarios } from './src/sampling'; + +export interface ServerConfig { + port: number; + evmPayTo: string; + svmPayTo: string; + evmNetwork: string; + svmNetwork: string; + facilitatorUrl?: string; +} // Load environment variables config(); // Parse command line arguments -const args = process.argv.slice(2); - -// Parse dev mode flag (sets network=base-sepolia, prod=false) -const isDevMode = args.includes('--dev') || args.includes('-d'); - -// Parse verbose flag -const isVerbose = args.includes('-v') || args.includes('--verbose'); - -// Parse language flags -const languageFilters: string[] = []; -if (args.includes('-ts') || args.includes('--typescript')) languageFilters.push('typescript'); -if (args.includes('-py') || args.includes('--python')) languageFilters.push('python'); -if (args.includes('-go') || args.includes('--go')) languageFilters.push('go'); - -// Parse protocol family flags -const protocolFamilyFilters: string[] = []; -args.forEach((arg, index) => { - if ((arg === '--family' || arg === '-f') && index + 1 < args.length) { - protocolFamilyFilters.push(args[index + 1]); - } else if (arg.startsWith('--family=')) { - protocolFamilyFilters.push(arg.split('=')[1]); - } -}); +const parsedArgs = parseArgs(); -// Parse filter arguments -const clientFilter = args.find(arg => arg.startsWith('--client='))?.split('=')[1]; -const serverFilter = args.find(arg => arg.startsWith('--server='))?.split('=')[1]; -const networkFilter = isDevMode ? ['base-sepolia', 'solana-devnet'] : - args.find(arg => arg.startsWith('--network='))?.split('=')[1] ? - [args.find(arg => arg.startsWith('--network='))?.split('=')[1]!] : - undefined; -const prodFilter = isDevMode ? 'false' : args.find(arg => arg.startsWith('--prod='))?.split('=')[1]; +interface Facilitator { + start: (config: { port: number; evmPrivateKey: string; svmPrivateKey: string; evmNetwork: string; svmNetwork: string; }) => Promise; + health: () => Promise<{ success: boolean }>; + getUrl: () => string; + stop: () => Promise; +} -// Parse log file argument -const logFile = args.find(arg => arg.startsWith('--log-file='))?.split('=')[1]; +// FacilitatorManager handles async facilitator lifecycle +class FacilitatorManager { + private facilitator: any; + private port: number; + private readyPromise: Promise; + private url: string | null = null; -// Initialize logger -loggerConfig({ logFile, verbose: isVerbose }); + constructor(facilitator: Facilitator, port: number, evmNetwork: string, svmNetwork: string) { + this.facilitator = facilitator; + this.port = port; -async function runCallProtectedScenario( - server: any, - client: any, - serverConfig: ServerConfig, - callConfig: ClientConfig -): Promise { - try { - verboseLog(` 🚀 Starting server with config: ${JSON.stringify(serverConfig, null, 2)}`); - await server.start(serverConfig); + // Start facilitator and health checks asynchronously + this.readyPromise = this.startAndWaitForHealth(evmNetwork, svmNetwork); + } - // Wait for server to be healthy before proceeding - let healthCheckAttempts = 0; - const maxHealthCheckAttempts = 10; + private async startAndWaitForHealth(evmNetwork: string, svmNetwork: string): Promise { + verboseLog(` 🏛️ Starting facilitator on port ${this.port}...`); + + await this.facilitator.start({ + port: this.port, + evmPrivateKey: process.env.FACILITATOR_EVM_PRIVATE_KEY, + svmPrivateKey: process.env.FACILITATOR_SVM_PRIVATE_KEY, + evmNetwork, + svmNetwork, + }); - while (healthCheckAttempts < maxHealthCheckAttempts) { - const healthResult = await server.health(); - verboseLog(` 🔍 Health check attempt ${healthCheckAttempts + 1}/${maxHealthCheckAttempts}: ${healthResult.success ? '✅' : '❌'}`); + // Wait for facilitator to be healthy + let attempts = 0; + const maxAttempts = 10; + + while (attempts < maxAttempts) { + const healthResult = await this.facilitator.health(); + verboseLog(` 🔍 Facilitator health check ${attempts + 1}/${maxAttempts}: ${healthResult.success ? '✅' : '❌'}`); if (healthResult.success) { - verboseLog(` ✅ Server is healthy after ${healthCheckAttempts + 1} attempts`); - break; + verboseLog(` ✅ Facilitator is healthy`); + this.url = this.facilitator.getUrl(); + return this.url; } - healthCheckAttempts++; + attempts++; await new Promise(resolve => setTimeout(resolve, 2000)); } - if (healthCheckAttempts >= maxHealthCheckAttempts) { - verboseLog(` ❌ Server failed to become healthy after ${maxHealthCheckAttempts} attempts`); - return { - success: false, - error: 'Server failed to become healthy after maximum attempts' - }; + verboseLog(` ❌ Facilitator failed to become healthy`); + return null; + } + + async ready(): Promise { + return this.readyPromise; + } + + getProxy(): any { + return this.facilitator; + } + + async stop(): Promise { + if (this.facilitator) { + await this.facilitator.stop(); } + } +} - verboseLog(` 📞 Making client call with config: ${JSON.stringify(callConfig, null, 2)}`); - const result = await client.call(callConfig); +async function startServer( + server: any, + serverConfig: ServerConfig +): Promise { + verboseLog(` 🚀 Starting server on port ${serverConfig.port}...`); + await server.start(serverConfig); + + // Wait for server to be healthy + let attempts = 0; + const maxAttempts = 10; + + while (attempts < maxAttempts) { + // Give server time to actually bind to port before first check + if (attempts === 0) { + await new Promise(resolve => setTimeout(resolve, 250)); + } + + const healthResult = await server.health(); + verboseLog(` 🔍 Server health check ${attempts + 1}/${maxAttempts}: ${healthResult.success ? '✅' : '❌'}`); - verboseLog(` 📊 Client call result: ${JSON.stringify(result, null, 2)}`); + if (healthResult.success) { + verboseLog(` ✅ Server is healthy`); + return true; + } + + attempts++; + await new Promise(resolve => setTimeout(resolve, 2000)); + } + + verboseLog(` ❌ Server failed to become healthy`); + return false; +} + +async function runClientTest( + client: any, + callConfig: ClientConfig +): Promise { + const verboseLogs: string[] = []; + + const bufferLog = (msg: string) => { + verboseLogs.push(msg); + }; + + try { + bufferLog(` 📞 Running client: ${JSON.stringify(callConfig, null, 2)}`); + const result = await client.call(callConfig); + bufferLog(` 📊 Client result: ${JSON.stringify(result, null, 2)}`); - if (result.success) { + // Check if the client execution succeeded + if (!result.success) { return { - success: true, - data: result.data, - status_code: result.status_code, - payment_response: result.payment_response + success: false, + error: result.error || 'Client execution failed', + verboseLogs }; - } else { + } + + // Check if we got a 402 Payment Required response (payment failed) + if (result.status_code === 402) { + const errorData = result.data as any; + const errorMsg = errorData?.error || 'Payment required - payment failed'; return { success: false, - error: result.error + error: `Payment failed (402): ${errorMsg}`, + data: result.data, + status_code: result.status_code, + verboseLogs }; } + // For protected endpoints, verify the payment actually succeeded + const paymentResponse = result.payment_response; + if (paymentResponse) { + // Payment was required - verify it succeeded + if (!paymentResponse.success) { + return { + success: false, + error: `Payment failed: ${paymentResponse.errorReason || 'unknown error'}`, + data: result.data, + status_code: result.status_code, + payment_response: paymentResponse, + verboseLogs + }; + } + + // Payment should have a transaction hash + if (!paymentResponse.transaction) { + return { + success: false, + error: 'Payment succeeded but no transaction hash returned', + data: result.data, + status_code: result.status_code, + payment_response: paymentResponse, + verboseLogs + }; + } + + // Payment should not have an error reason + if (paymentResponse.errorReason) { + return { + success: false, + error: `Payment has error reason: ${paymentResponse.errorReason}`, + data: result.data, + status_code: result.status_code, + payment_response: paymentResponse, + verboseLogs + }; + } + } + + // All checks passed + return { + success: true, + data: result.data, + status_code: result.status_code, + payment_response: paymentResponse, + verboseLogs + }; } catch (error) { - verboseLog(` 💥 Scenario failed with error: ${error}`); + bufferLog(` 💥 Client failed: ${error}`); return { success: false, - error: error instanceof Error ? error.message : String(error) + error: error instanceof Error ? error.message : String(error), + verboseLogs }; } finally { - // Cleanup - verboseLog(` 🧹 Cleaning up server and client processes`); - await server.stop(); await client.forceStop(); } } async function runTest() { // Show help if requested - if (args.includes('-h') || args.includes('--help')) { - console.log('Usage: npm test [options]'); - console.log(''); - console.log('Options:'); - console.log('Environment:'); - console.log(' -d, --dev Development mode (base-sepolia, no CDP)'); - console.log(' -v, --verbose Enable verbose logging'); - console.log(' -ts, --typescript Include TypeScript implementations'); - console.log(' -py, --python Include Python implementations'); - console.log(' -go, --go Include Go implementations'); - console.log(''); - console.log('Filters:'); - console.log(' --log-file= Save verbose output to file'); - console.log(' --client= Filter by client name (e.g., httpx, axios)'); - console.log(' --server= Filter by server name (e.g., express, fastapi)'); - console.log(' --network= Filter by network (base, base-sepolia)'); - console.log(' --prod= Filter by production vs testnet scenarios'); - console.log(' -f, --family= Filter by protocol family (evm, svm) - can be used multiple times'); - console.log(' -h, --help Show this help message'); - console.log(''); - console.log('Examples:'); - console.log(' pnpm test # Run all tests'); - console.log(' pnpm test -d # Run tests in development mode'); - console.log(' pnpm test -py -go # Test Python and Go implementations'); - console.log(' pnpm test -ts --client=axios # Test TypeScript axios client'); - console.log(' pnpm test -d -py # Dev mode, Python implementations only'); - console.log(' pnpm test --network=base --prod=true # Base mainnet only'); - console.log(' pnpm test -f evm # Test EVM protocol family only'); - console.log(' pnpm test -f evm -f svm # Test both EVM and SVM protocol families'); - console.log(''); + if (parsedArgs.showHelp) { + printHelp(); return; } + // Initialize logger + loggerConfig({ logFile: parsedArgs.logFile, verbose: parsedArgs.verbose }); + log('🚀 Starting X402 E2E Test Suite'); log('==============================='); @@ -157,144 +241,407 @@ async function runTest() { const serverSvmAddress = process.env.SERVER_SVM_ADDRESS; const clientEvmPrivateKey = process.env.CLIENT_EVM_PRIVATE_KEY; const clientSvmPrivateKey = process.env.CLIENT_SVM_PRIVATE_KEY; - const serverPort = parseInt(process.env.SERVER_PORT || '4021'); + const facilitatorEvmPrivateKey = process.env.FACILITATOR_EVM_PRIVATE_KEY; + const facilitatorSvmPrivateKey = process.env.FACILITATOR_SVM_PRIVATE_KEY; - if (!serverEvmAddress || !serverSvmAddress || !clientEvmPrivateKey || !clientSvmPrivateKey) { + if (!serverEvmAddress || !serverSvmAddress || !clientEvmPrivateKey || !clientSvmPrivateKey || !facilitatorEvmPrivateKey || !facilitatorSvmPrivateKey) { errorLog('❌ Missing required environment variables:'); - errorLog(' SERVER_EVM_ADDRESS, SERVER_SVM_ADDRESS, CLIENT_EVM_PRIVATE_KEY and CLIENT_SVM_PRIVATE_KEY must be set'); + errorLog(' SERVER_EVM_ADDRESS, SERVER_SVM_ADDRESS, CLIENT_EVM_PRIVATE_KEY, CLIENT_SVM_PRIVATE_KEY, FACILITATOR_EVM_PRIVATE_KEY, and FACILITATOR_SVM_PRIVATE_KEY must be set'); process.exit(1); } - // Discover all servers and clients - const discovery = new TestDiscovery('.'); + // Discover all servers, clients, and facilitators (always include legacy) + const discovery = new TestDiscovery('.', true); // Always discover legacy + + const allClients = discovery.discoverClients(); + const allServers = discovery.discoverServers(); + const allFacilitators = discovery.discoverFacilitators(); + discovery.printDiscoverySummary(); - const scenarios = discovery.generateTestScenarios(); + // Generate all possible scenarios + const allScenarios = discovery.generateTestScenarios(); - if (scenarios.length === 0) { + if (allScenarios.length === 0) { log('❌ No test scenarios found'); return; } - // Count active filters - interface FilterInfo { - name: string; - value: string; + let filters: TestFilters; + let selectedExtensions: string[] | undefined; + + // Interactive or programmatic mode + if (parsedArgs.mode === 'interactive') { + const selections = await runInteractiveMode( + allClients, + allServers, + allFacilitators, + allScenarios, + parsedArgs.minimize + ); + + if (!selections) { + log('\n❌ Cancelled by user'); + return; + } + + filters = selections; + selectedExtensions = selections.extensions; + } else { + log('\n🤖 Programmatic Mode'); + log('===================\n'); + + filters = parsedArgs.filters; + selectedExtensions = parsedArgs.filters.extensions; + + // Print active filters + const filterEntries = Object.entries(filters).filter(([_, v]) => v && (Array.isArray(v) ? v.length > 0 : true)); + if (filterEntries.length > 0) { + log('Active filters:'); + filterEntries.forEach(([key, value]) => { + if (Array.isArray(value) && value.length > 0) { + log(` - ${key}: ${value.join(', ')}`); + } + }); + log(''); + } } - const activeFilters: FilterInfo[] = [ - languageFilters.length > 0 && { name: 'Languages', value: languageFilters.join(', ') }, - clientFilter && { name: 'Client', value: clientFilter }, - serverFilter && { name: 'Server', value: serverFilter }, - networkFilter && { name: 'Network', value: networkFilter.join(', ') }, - prodFilter && { name: 'Production', value: prodFilter }, - protocolFamilyFilters.length > 0 && { name: 'Protocol Families', value: protocolFamilyFilters.join(', ') } - ].filter((f): f is FilterInfo => f !== null && f !== undefined); - - log('📊 Test Scenarios'); - log('==============='); - log(`Total unfiltered scenarios: ${scenarios.length}`); - if (activeFilters.length > 0) { - log(`Active filters (${activeFilters.length}):`); - activeFilters.forEach(filter => { - log(` - ${filter.name}: ${filter.value}`); - }); + // Apply filters to scenarios + let filteredScenarios = filterScenarios(allScenarios, filters); + + if (filteredScenarios.length === 0) { + log('❌ No scenarios match the selections'); + log('💡 Try selecting more options or run without filters\n'); + return; + } + + // Apply coverage-based minimization if --min flag is set + if (parsedArgs.minimize) { + filteredScenarios = minimizeScenarios(filteredScenarios); + + if (filteredScenarios.length === 0) { + log('❌ All scenarios are already covered'); + log('💡 This should not happen - coverage tracking may have an issue\n'); + return; + } } else { - log('No active filters'); + log(`\n✅ ${filteredScenarios.length} scenarios selected`); } - // Filter scenarios based on command line arguments - const filteredScenarios = scenarios.filter(scenario => { - // Language filter - if languages specified, both client and server must match one of them - if (languageFilters.length > 0) { - const matchesLanguage = languageFilters.some(lang => - scenario.client.config.language.includes(lang) && - scenario.server.config.language.includes(lang) - ); - if (!matchesLanguage) return false; + if (selectedExtensions && selectedExtensions.length > 0) { + log(`🎁 Extensions enabled: ${selectedExtensions.join(', ')}`); + } + log(''); + + // Collect unique facilitators and servers + const uniqueFacilitators = new Map(); + const uniqueServers = new Map(); + + filteredScenarios.forEach(scenario => { + if (scenario.facilitator) { + uniqueFacilitators.set(scenario.facilitator.name, scenario.facilitator); + } + uniqueServers.set(scenario.server.name, scenario.server); + }); + + // Validate environment variables for all selected facilitators + log('\n🔍 Validating facilitator environment variables...\n'); + const missingEnvVars: { facilitatorName: string; missingVars: string[] }[] = []; + + // Environment variables managed by the test framework (don't require user to set) + const systemManagedVars = new Set(['PORT', 'EVM_PRIVATE_KEY', 'SVM_PRIVATE_KEY', 'EVM_NETWORK', 'SVM_NETWORK']); + + for (const [facilitatorName, facilitator] of uniqueFacilitators) { + const requiredVars = facilitator.config.environment?.required || []; + const missing: string[] = []; + + for (const envVar of requiredVars) { + // Skip variables managed by the test framework + if (systemManagedVars.has(envVar)) { + continue; + } + + if (!process.env[envVar]) { + missing.push(envVar); + } + } + + if (missing.length > 0) { + missingEnvVars.push({ facilitatorName, missingVars: missing }); + } + } + + if (missingEnvVars.length > 0) { + errorLog('❌ Missing required environment variables for selected facilitators:\n'); + for (const { facilitatorName, missingVars } of missingEnvVars) { + errorLog(` ${facilitatorName}:`); + missingVars.forEach(varName => errorLog(` - ${varName}`)); } + errorLog('\n💡 Please set the required environment variables and try again.\n'); + process.exit(1); + } + + log(' ✅ All required environment variables are present\n'); + + interface DetailedTestResult { + testNumber: number; + client: string; + server: string; + endpoint: string; + facilitator: string; + protocolFamily: string; + passed: boolean; + error?: string; + transaction?: string; + network?: string; + } - // Client filter - if set, only run tests for this client - if (clientFilter && scenario.client.name !== clientFilter) return false; + let testResults: DetailedTestResult[] = []; + let testNumber = 0; + let currentPort = 4022; - // Server filter - if set, only run tests for this server - if (serverFilter && scenario.server.name !== serverFilter) return false; + // Assign ports and start all facilitators + const facilitatorManagers = new Map(); + const serverPorts = new Map(); // Track assigned ports for each server - // Network filter - if set, only run tests for these networks - if (networkFilter && !(networkFilter.includes(scenario.facilitatorNetworkCombo.network))) return false; + // Assign ports to servers (they'll reuse these ports across restarts) + for (const [serverName] of uniqueServers) { + const port = currentPort++; + serverPorts.set(serverName, port); + } - // Protocol family filter - if set, only run tests for these protocol families - if (protocolFamilyFilters.length > 0 && !protocolFamilyFilters.includes(scenario.protocolFamily)) return false; + // Start all facilitators with unique ports + for (const [facilitatorName, facilitator] of uniqueFacilitators) { + const port = currentPort++; + log(`\n🏛️ Starting facilitator: ${facilitatorName} on port ${port}`); + + const manager = new FacilitatorManager( + facilitator.proxy, + port, + 'eip155:84532', + 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1' + ); + facilitatorManagers.set(facilitatorName, manager); + } - // Production filter - if set, filter by production vs testnet scenarios - if (prodFilter !== undefined) { - const isProd = prodFilter.toLowerCase() === 'true'; - const isTestnetOnly = !scenario.facilitatorNetworkCombo.useCdpFacilitator && (scenario.facilitatorNetworkCombo.network === 'base-sepolia' || scenario.facilitatorNetworkCombo.network === 'solana-devnet'); - if (isProd && isTestnetOnly) return false; - if (!isProd && !isTestnetOnly) return false; + // Wait for all facilitators to be ready + log('\n⏳ Waiting for all facilitators to be ready...'); + const facilitatorUrls = new Map(); + + for (const [facilitatorName, manager] of facilitatorManagers) { + const url = await manager.ready(); + if (!url) { + log(`❌ Failed to start facilitator ${facilitatorName}`); + process.exit(1); } + facilitatorUrls.set(facilitatorName, url); + log(` ✅ Facilitator ${facilitatorName} ready at ${url}`); + } - return true; - }); + log('\n✅ All facilitators are ready! Servers will be started/restarted as needed per test scenario.\n'); - if (filteredScenarios.length === 0) { - log('❌ No scenarios match the active filters'); - return; + // Group scenarios by server + facilitator combination + // This ensures we restart servers when switching facilitators + interface ServerFacilitatorCombo { + serverName: string; + facilitatorName: string | undefined; + scenarios: typeof filteredScenarios; + } + + const serverFacilitatorCombos: ServerFacilitatorCombo[] = []; + const groupKey = (serverName: string, facilitatorName: string | undefined) => + `${serverName}::${facilitatorName || 'none'}`; + + const comboMap = new Map(); + + for (const scenario of filteredScenarios) { + const key = groupKey(scenario.server.name, scenario.facilitator?.name); + if (!comboMap.has(key)) { + comboMap.set(key, []); + } + comboMap.get(key)!.push(scenario); } - log(`Scenarios to run: ${filteredScenarios.length}`); + // Convert map to array of combos + for (const [key, scenarios] of comboMap) { + const firstScenario = scenarios[0]; + serverFacilitatorCombos.push({ + serverName: firstScenario.server.name, + facilitatorName: firstScenario.facilitator?.name, + scenarios, + }); + } + + log(`🔧 Server/Facilitator combinations: ${serverFacilitatorCombos.length}`); + serverFacilitatorCombos.forEach(combo => { + log(` • ${combo.serverName} + ${combo.facilitatorName || 'none'}: ${combo.scenarios.length} test(s)`); + }); log(''); - // Run filtered scenarios - let passed = 0; - let failed = 0; + // Track running servers to stop/restart them as needed + const runningServers = new Map(); // serverName -> server proxy - for (let i = 0; i < filteredScenarios.length; i++) { - const scenario = filteredScenarios[i]; - const testNumber = i + 1; - const combo = scenario.facilitatorNetworkCombo; - const comboLabel = `useCdpFacilitator=${combo.useCdpFacilitator}, networks=[${combo.network}]`; - const testName = `${scenario.client.name} → ${scenario.server.name} → ${scenario.endpoint.path} [${comboLabel}]`; + // Track which facilitators processed which servers (for discovery validation) + const facilitatorServerMap = new Map>(); // facilitatorName -> Set + + // Run tests grouped by server+facilitator combination + for (const combo of serverFacilitatorCombos) { + const { serverName, facilitatorName, scenarios } = combo; + const server = uniqueServers.get(serverName)!; + const port = serverPorts.get(serverName)!; + + // Track that this facilitator is processing this server + if (facilitatorName) { + if (!facilitatorServerMap.has(facilitatorName)) { + facilitatorServerMap.set(facilitatorName, new Set()); + } + facilitatorServerMap.get(facilitatorName)!.add(serverName); + } + + // Stop server if it's already running (from previous combo) + if (runningServers.has(serverName)) { + verboseLog(` 🔄 Restarting ${serverName} with new facilitator: ${facilitatorName || 'none'}`); + await runningServers.get(serverName).stop(); + runningServers.delete(serverName); + await new Promise(resolve => setTimeout(resolve, 2000)); // Wait for port to be released + } + + // Start server with the appropriate facilitator + const facilitatorUrl = facilitatorName ? + facilitatorUrls.get(facilitatorName) : undefined; + + log(`\n🚀 Starting server: ${serverName} (port ${port}) with facilitator: ${facilitatorName || 'none'}`); const serverConfig: ServerConfig = { - port: serverPort, - useCdpFacilitator: combo.useCdpFacilitator, + port, evmPayTo: serverEvmAddress, svmPayTo: serverSvmAddress, - evmNetwork: scenario.protocolFamily === 'evm' ? combo.network : 'base-sepolia', - svmNetwork: scenario.protocolFamily === 'svm' ? combo.network : 'solana-devnet', + evmNetwork: 'eip155:84532', + svmNetwork: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', + facilitatorUrl, }; - const callConfig: ClientConfig = { - evmPrivateKey: clientEvmPrivateKey, - svmPrivateKey: clientSvmPrivateKey, - serverUrl: scenario.server.proxy.getUrl(), - endpointPath: scenario.endpoint.path - }; + const started = await startServer(server.proxy, serverConfig); + if (!started) { + log(`❌ Failed to start server ${serverName}`); + process.exit(1); + } + log(` ✅ Server ${serverName} ready\n`); + runningServers.set(serverName, server.proxy); + + // Run all tests for this server+facilitator combination + for (const scenario of scenarios) { + testNumber++; + const facilitatorLabel = scenario.facilitator ? ` via ${scenario.facilitator.name}` : ''; + const testName = `${scenario.client.name} → ${scenario.server.name} → ${scenario.endpoint.path}${facilitatorLabel}`; + + const clientConfig: ClientConfig = { + evmPrivateKey: clientEvmPrivateKey, + svmPrivateKey: clientSvmPrivateKey, + serverUrl: `http://localhost:${port}`, + endpointPath: scenario.endpoint.path, + }; - try { - log(`🧪 Testing #${testNumber}: ${testName}`); - const result = await runCallProtectedScenario( - scenario.server.proxy, - scenario.client.proxy, - serverConfig, - callConfig - ); - - if (result.success) { - verboseLog(` ✅ Test passed`); - passed++; - } else { - log(`❌ #${testNumber} ${testName}: ${result.error}`); - verboseLog(` 🔍 Error details: ${JSON.stringify(result, null, 2)}`); - failed++; + try { + log(`🧪 Test #${testNumber}: ${testName}`); + const result = await runClientTest(scenario.client.proxy, clientConfig); + + const detailedResult: DetailedTestResult = { + testNumber, + client: scenario.client.name, + server: scenario.server.name, + endpoint: scenario.endpoint.path, + facilitator: scenario.facilitator?.name || 'none', + protocolFamily: scenario.protocolFamily, + passed: result.success, + error: result.error, + transaction: result.payment_response?.transaction, + network: result.payment_response?.network, + }; + + if (result.success) { + log(` ✅ Test passed`); + testResults.push(detailedResult); + } else { + log(` ❌ Test failed: ${result.error}`); + + // Print buffered verbose logs only for failed tests + if (result.verboseLogs && result.verboseLogs.length > 0) { + log(` 🔍 Verbose logs:`); + result.verboseLogs.forEach(logLine => log(logLine)); + } + + verboseLog(` 🔍 Error details: ${JSON.stringify(result, null, 2)}`); + testResults.push(detailedResult); + } + } catch (error) { + const errorMsg = error instanceof Error ? error.message : String(error); + log(` ❌ Test failed with exception: ${errorMsg}`); + verboseLog(` 🔍 Exception details: ${error}`); + testResults.push({ + testNumber, + client: scenario.client.name, + server: scenario.server.name, + endpoint: scenario.endpoint.path, + facilitator: scenario.facilitator?.name || 'none', + protocolFamily: scenario.protocolFamily, + passed: false, + error: errorMsg, + }); } - } catch (error) { - log(`❌ #${testNumber} ${testName}: ${error}`); - verboseLog(` 🔍 Exception details: ${error}`); - failed++; + + // Delay between tests to prevent timing/state/nonce issues + await new Promise(resolve => setTimeout(resolve, 5000)); } + + // Stop server after running all tests for this combo + verboseLog(` 🛑 Stopping ${serverName} (finished combo)`); + await server.proxy.stop(); + runningServers.delete(serverName); + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for cleanup + } + + // Run discovery validation before cleanup (while facilitators are still running) + const facilitatorsWithConfig = Array.from(uniqueFacilitators.values()).map((f: any) => ({ + proxy: facilitatorManagers.get(f.name)!.getProxy(), + config: f.config, + })); + + const serversArray = Array.from(uniqueServers.values()); + + // Run discovery validation if bazaar extension is enabled + const showBazaarOutput = shouldShowExtensionOutput('bazaar', selectedExtensions); + if (showBazaarOutput && shouldRunDiscoveryValidation(facilitatorsWithConfig, serversArray)) { + log('\n🔍 Running Bazaar Discovery Validation...\n'); + await handleDiscoveryValidation( + facilitatorsWithConfig, + serversArray, + serverPorts, + facilitatorServerMap + ); + } + + // Clean up facilitators (servers already stopped in test loop) + log('\n🧹 Cleaning up...'); + + // Stop any servers that might still be running + for (const [serverName, serverProxy] of runningServers) { + log(` 🛑 Stopping server: ${serverName}`); + await serverProxy.stop(); + } + + // Stop all facilitators + const facilitatorStopPromises: Promise[] = []; + for (const [facilitatorName, manager] of facilitatorManagers) { + log(` 🛑 Stopping facilitator: ${facilitatorName}`); + facilitatorStopPromises.push(manager.stop()); } + await Promise.all(facilitatorStopPromises); + + // Calculate totals + const passed = testResults.filter(r => r.passed).length; + const failed = testResults.filter(r => !r.passed).length; // Summary log(''); @@ -303,21 +650,106 @@ async function runTest() { log(`✅ Passed: ${passed}`); log(`❌ Failed: ${failed}`); log(`📈 Total: ${passed + failed}`); + log(''); + + // Detailed results table + log('📋 Detailed Test Results'); + log('========================'); + log(''); + + // Group by status + const passedTests = testResults.filter(r => r.passed); + const failedTests = testResults.filter(r => !r.passed); + + if (passedTests.length > 0) { + log('✅ PASSED TESTS:'); + log(''); + passedTests.forEach(test => { + const txInfo = test.transaction ? ` | Tx: ${test.transaction.substring(0, 10)}...` : ''; + log(` #${test.testNumber.toString().padStart(2, ' ')}: ${test.client} → ${test.server} → ${test.endpoint}`); + log(` Facilitator: ${test.facilitator} | Network: ${test.network || 'N/A'}${txInfo}`); + }); + log(''); + } + + if (failedTests.length > 0) { + log('❌ FAILED TESTS:'); + log(''); + failedTests.forEach(test => { + log(` #${test.testNumber.toString().padStart(2, ' ')}: ${test.client} → ${test.server} → ${test.endpoint}`); + log(` Facilitator: ${test.facilitator}`); + log(` Error: ${test.error || 'Unknown error'}`); + }); + log(''); + } + + // Breakdown by facilitator + const facilitatorBreakdown = testResults.reduce((acc, test) => { + const key = test.facilitator; + if (!acc[key]) acc[key] = { passed: 0, failed: 0 }; + if (test.passed) acc[key].passed++; + else acc[key].failed++; + return acc; + }, {} as Record); + + log('📊 Breakdown by Facilitator:'); + Object.entries(facilitatorBreakdown).forEach(([facilitator, stats]) => { + const total = stats.passed + stats.failed; + const passRate = total > 0 ? Math.round((stats.passed / total) * 100) : 0; + log(` ${facilitator.padEnd(15)} ✅ ${stats.passed} / ❌ ${stats.failed} (${passRate}%)`); + }); + log(''); + + // Breakdown by server + const serverBreakdown = testResults.reduce((acc, test) => { + const key = test.server; + if (!acc[key]) acc[key] = { passed: 0, failed: 0 }; + if (test.passed) acc[key].passed++; + else acc[key].failed++; + return acc; + }, {} as Record); + + log('📊 Breakdown by Server:'); + Object.entries(serverBreakdown).forEach(([server, stats]) => { + const total = stats.passed + stats.failed; + const passRate = total > 0 ? Math.round((stats.passed / total) * 100) : 0; + log(` ${server.padEnd(20)} ✅ ${stats.passed} / ❌ ${stats.failed} (${passRate}%)`); + }); + log(''); + + // Breakdown by client + const clientBreakdown = testResults.reduce((acc, test) => { + const key = test.client; + if (!acc[key]) acc[key] = { passed: 0, failed: 0 }; + if (test.passed) acc[key].passed++; + else acc[key].failed++; + return acc; + }, {} as Record); + + log('📊 Breakdown by Client:'); + Object.entries(clientBreakdown).forEach(([client, stats]) => { + const total = stats.passed + stats.failed; + const passRate = total > 0 ? Math.round((stats.passed / total) * 100) : 0; + log(` ${client.padEnd(20)} ✅ ${stats.passed} / ❌ ${stats.failed} (${passRate}%)`); + }); + log(''); // Protocol family breakdown - const protocolBreakdown = filteredScenarios.reduce((acc, scenario) => { - const key = scenario.protocolFamily; - if (!acc[key]) acc[key] = { passed: 0, failed: 0, total: 0 }; - acc[key].total++; + const protocolBreakdown = testResults.reduce((acc, test) => { + const key = test.protocolFamily; + if (!acc[key]) acc[key] = { passed: 0, failed: 0 }; + if (test.passed) acc[key].passed++; + else acc[key].failed++; return acc; - }, {} as Record); + }, {} as Record); if (Object.keys(protocolBreakdown).length > 1) { - log(''); log('📊 Protocol Family Breakdown:'); Object.entries(protocolBreakdown).forEach(([protocol, stats]) => { - log(` ${protocol.toUpperCase()}: ${stats.total} scenarios tested`); + const total = stats.passed + stats.failed; + log(` ${protocol.toUpperCase()}: ✅ ${stats.passed} / ❌ ${stats.failed} / 📈 ${total} total`); }); + log(''); } // Close logger diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json index 3df0e399f..2f152d983 100644 --- a/e2e/tsconfig.json +++ b/e2e/tsconfig.json @@ -1,12 +1,12 @@ { "compilerOptions": { "target": "ES2020", - "module": "commonjs", + "module": "ES2020", + "moduleResolution": "bundler", "lib": [ "ES2020" ], "outDir": "./dist", - "rootDir": ".", "strict": true, "esModuleInterop": true, "skipLibCheck": true, diff --git a/examples/go/clients/advanced/.env-example b/examples/go/clients/advanced/.env-example new file mode 100644 index 000000000..066c1bc2b --- /dev/null +++ b/examples/go/clients/advanced/.env-example @@ -0,0 +1,3 @@ +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= +SERVER_URL=http://localhost:4021/weather diff --git a/examples/go/clients/advanced/.gitignore b/examples/go/clients/advanced/.gitignore new file mode 100644 index 000000000..f10aed5af --- /dev/null +++ b/examples/go/clients/advanced/.gitignore @@ -0,0 +1,25 @@ +# Environment variables +.env + +# Binaries +*.exe +*.exe~ +*.dll +*.so +*.dylib +advanced +client +main + +# Go build artifacts +*.test +*.out +go.sum + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + diff --git a/examples/go/clients/advanced/README.md b/examples/go/clients/advanced/README.md new file mode 100644 index 000000000..9239a260c --- /dev/null +++ b/examples/go/clients/advanced/README.md @@ -0,0 +1,168 @@ +# Advanced x402 Client Examples + +Advanced patterns for x402 Go clients demonstrating payment lifecycle hooks, network preferences, and production-ready transports. + +## Prerequisites + +- Go 1.21 or higher +- An Ethereum private key (testnet recommended) +- A running x402 server (see [server examples](../../servers/)) +- Familiarity with the [basic HTTP client](../http/) + +## Setup + +1. Install dependencies: + +```bash +go mod download +``` + +2. Create a `.env` file: + +```bash +# Required +EVM_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + +# Optional +SERVER_URL=http://localhost:4021/weather +``` + +## Available Examples + +Each example demonstrates a specific advanced pattern: + +| Example | Command | Description | +|---------|---------|-------------| +| `custom-transport` | `go run . custom-transport` | Custom HTTP transport with retry logic | +| `error-recovery` | `go run . error-recovery` | Error classification and recovery | +| `multi-network-priority` | `go run . multi-network-priority` | Network-specific signer registration | +| `hooks` | `go run . hooks` | Payment lifecycle hooks | + +## Testing the Examples + +Start a server first: + +```bash +cd ../../servers/gin +go run main.go +``` + +Then run the examples: + +```bash +cd ../../clients/advanced +go run . hooks +``` + +## Example: Payment Lifecycle Hooks + +Register custom logic at different payment stages for observability and control: + +```go +import ( + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" +) + +signer, _ := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY")) + +client := x402.Newx402Client(). + Register("eip155:*", evm.NewExactEvmScheme(signer)) + +// OnBeforePaymentCreation: validation before payment +client.OnBeforePaymentCreation(func(ctx x402.PaymentCreationContext) (*x402.BeforePaymentCreationHookResult, error) { + fmt.Printf("Creating payment for: %s\n", ctx.SelectedRequirements.GetNetwork()) + // Abort payment by returning: &x402.BeforePaymentCreationHookResult{Abort: true, Reason: "Not allowed"} + return nil, nil +}) + +// OnAfterPaymentCreation: logging after successful payment +client.OnAfterPaymentCreation(func(ctx x402.PaymentCreatedContext) error { + fmt.Printf("Payment created: version %d\n", ctx.Version) + return nil +}) + +// OnPaymentCreationFailure: error recovery +client.OnPaymentCreationFailure(func(ctx x402.PaymentCreationFailureContext) (*x402.PaymentCreationFailureHookResult, error) { + fmt.Printf("Payment failed: %v\n", ctx.Error) + // Recover by returning: &x402.PaymentCreationFailureHookResult{Recovered: true, Payload: altPayload} + return nil, nil +}) + +httpClient := x402http.Newx402HTTPClient(client) +wrappedClient := x402http.WrapHTTPClientWithPayment(http.DefaultClient, httpClient) + +resp, _ := wrappedClient.Get("http://localhost:4021/weather") +``` + +Available hooks: + +- `OnBeforePaymentCreation` — Run before payment creation (can abort) +- `OnAfterPaymentCreation` — Run after successful payment creation +- `OnPaymentCreationFailure` — Run when payment creation fails (can recover) + +**Use case:** Log payment events, custom validation, retry/recovery logic, metrics collection. + +## Example: Multi-Network Priority + +Configure network-specific signers with wildcard fallback: + +```go +client := x402.Newx402Client(). + // Specific networks (highest priority) + Register("eip155:1", evm.NewExactEvmScheme(mainnetSigner)). + Register("eip155:8453", evm.NewExactEvmScheme(baseSigner)). + Register("eip155:84532", evm.NewExactEvmScheme(testnetSigner)). + // Wildcard fallback (lowest priority) + Register("eip155:*", evm.NewExactEvmScheme(defaultSigner)) +``` + +More specific registrations always override wildcards. + +**Use case:** Different signers per network, mainnet/testnet separation, multi-chain applications. + +## Example: Custom Transport + +Build a custom HTTP transport with retry logic and timing: + +```go +// RetryTransport wraps a transport with exponential backoff +type RetryTransport struct { + Transport http.RoundTripper + MaxRetries int + RetryDelay time.Duration +} + +// Stack transports: Base -> Timing -> Retry -> x402 Payment +baseTransport := &http.Transport{ + MaxIdleConns: 100, + MaxIdleConnsPerHost: 10, + IdleConnTimeout: 90 * time.Second, +} + +timingTransport := &TimingTransport{Transport: baseTransport} +retryTransport := &RetryTransport{Transport: timingTransport, MaxRetries: 3, RetryDelay: 100 * time.Millisecond} + +wrappedClient := x402http.WrapHTTPClientWithPayment( + &http.Client{Transport: retryTransport, Timeout: 30 * time.Second}, + httpClient, +) +``` + +**Use case:** Automatic retry on transient failures, request metrics, connection pooling. + +## Hook Best Practices + +1. **Keep hooks fast** — Avoid blocking operations +2. **Handle errors gracefully** — Don't panic in hooks +3. **Log appropriately** — Use structured logging +4. **Avoid side effects in before hooks** — Only use for validation + +## Next Steps + +- **[Basic HTTP Client](../http/)** — Start here if you haven't already +- **[Custom Client](../custom/)** — Learn the internals +- **[Server Examples](../../servers/)** — Build complementary servers + diff --git a/examples/go/clients/advanced/custom_transport.go b/examples/go/clients/advanced/custom_transport.go new file mode 100644 index 000000000..7b8ee4c2c --- /dev/null +++ b/examples/go/clients/advanced/custom_transport.go @@ -0,0 +1,140 @@ +package main + +import ( + "context" + "fmt" + "net/http" + "time" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" +) + +/** + * Custom Transport with Retry Logic and Circuit Breaker + * + * This example demonstrates how to implement a custom HTTP transport that: + * - Automatically retries failed requests + * - Implements exponential backoff + * - Includes circuit breaker pattern + * - Sets custom timeouts + * - Adds request tracing + */ + +// RetryTransport wraps an HTTP transport with retry logic +type RetryTransport struct { + Transport http.RoundTripper + MaxRetries int + RetryDelay time.Duration +} + +// RoundTrip implements http.RoundTripper with retry logic +func (t *RetryTransport) RoundTrip(req *http.Request) (*http.Response, error) { + var resp *http.Response + var err error + + for attempt := 0; attempt <= t.MaxRetries; attempt++ { + if attempt > 0 { + // Exponential backoff + delay := t.RetryDelay * time.Duration(1< Retry logic -> Timing -> x402 Payment + baseTransport := &http.Transport{ + MaxIdleConns: 100, + MaxIdleConnsPerHost: 10, + IdleConnTimeout: 90 * time.Second, + DisableCompression: false, + } + + // Add timing wrapper + timingTransport := &TimingTransport{ + Transport: baseTransport, + } + + // Add retry wrapper + retryTransport := &RetryTransport{ + Transport: timingTransport, + MaxRetries: 3, + RetryDelay: 100 * time.Millisecond, + } + + // Wrap with x402 payment handling + wrappedClient := x402http.WrapHTTPClientWithPayment(&http.Client{ + Transport: retryTransport, + Timeout: 30 * time.Second, + }, httpClient) + + // Make request + fmt.Printf("🌐 Making request to: %s\n", url) + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return err + } + + resp, err := wrappedClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + return printResponse(resp, "Response with custom transport") +} + diff --git a/examples/go/clients/advanced/error_recovery.go b/examples/go/clients/advanced/error_recovery.go new file mode 100644 index 000000000..b4ad618f2 --- /dev/null +++ b/examples/go/clients/advanced/error_recovery.go @@ -0,0 +1,165 @@ +package main + +import ( + "context" + "fmt" + "net/http" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" +) + +/** + * Advanced Error Recovery Example + * + * This example demonstrates sophisticated error handling strategies: + * - Automatic recovery from payment creation failures + * - Custom error classification + * - Fallback payment methods + * - Detailed error logging and metrics + */ + +type ErrorRecoveryClient struct { + client *x402.X402Client + fallbackEnabled bool + attemptCount int +} + +func runErrorRecoveryExample(ctx context.Context, evmPrivateKey, url string) error { + fmt.Println("🛡️ Creating client with advanced error recovery...\n") + + // Create signer + evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(evmPrivateKey) + if err != nil { + return err + } + + // Create x402 client with comprehensive error handling + client := x402.Newx402Client(). + Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + + // Recovery counter + recoveryAttempts := 0 + successfulRecoveries := 0 + + // OnBeforePaymentCreation: Pre-flight validation + client.OnBeforePaymentCreation(func(ctx x402.PaymentCreationContext) (*x402.BeforePaymentCreationHookResult, error) { + fmt.Printf("🔍 [Pre-flight] Validating payment requirements...\n") + fmt.Printf(" Network: %s, Scheme: %s\n", ctx.SelectedRequirements.GetNetwork(), ctx.SelectedRequirements.GetScheme()) + + // Could implement custom validation logic here + // For example, check if user has sufficient balance before creating payment + + return nil, nil // Continue + }) + + // OnPaymentCreationFailure: Advanced error recovery + client.OnPaymentCreationFailure(func(ctx x402.PaymentCreationFailureContext) (*x402.PaymentCreationFailureHookResult, error) { + recoveryAttempts++ + fmt.Printf("❌ [Error Recovery] Payment creation failed (attempt %d)\n", recoveryAttempts) + fmt.Printf(" Error: %v\n", ctx.Error) + fmt.Printf(" Network: %s\n", ctx.SelectedRequirements.GetNetwork()) + fmt.Printf(" Scheme: %s\n", ctx.SelectedRequirements.GetScheme()) + + // Classify error type + errorType := classifyError(ctx.Error) + fmt.Printf(" Error type: %s\n", errorType) + + // Recovery strategy based on error type + switch errorType { + case "network": + fmt.Println(" 🔄 Network error - will retry automatically") + return nil, nil // Let retry logic handle it + + case "insufficient_balance": + fmt.Println(" 💰 Insufficient balance - cannot recover") + return nil, ctx.Error // Propagate error + + case "signing_error": + fmt.Println(" 🔑 Signing error - attempting recovery...") + // In a real scenario, you might try with a different signer or method + successfulRecoveries++ + return nil, nil + + default: + fmt.Println(" ⚠️ Unknown error - will not recover") + return nil, ctx.Error + } + }) + + // OnAfterPaymentCreation: Success logging + client.OnAfterPaymentCreation(func(ctx x402.PaymentCreatedContext) error { + fmt.Printf("✅ [Success] Payment created\n") + if recoveryAttempts > 0 { + fmt.Printf(" Recovered after %d attempts\n", recoveryAttempts) + } + return nil + }) + + // Wrap HTTP client + httpClient := x402http.Newx402HTTPClient(client) + wrappedClient := x402http.WrapHTTPClientWithPayment(http.DefaultClient, httpClient) + + // Make request + fmt.Printf("\n🌐 Making request to: %s\n\n", url) + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return err + } + + resp, err := wrappedClient.Do(req) + if err != nil { + return fmt.Errorf("request failed after recovery attempts: %w", err) + } + defer resp.Body.Close() + + // Print statistics + fmt.Printf("\n📊 Error Recovery Statistics:\n") + fmt.Printf(" Total recovery attempts: %d\n", recoveryAttempts) + fmt.Printf(" Successful recoveries: %d\n", successfulRecoveries) + fmt.Printf(" Final status: %d\n\n", resp.StatusCode) + + return printResponse(resp, "Response after error recovery") +} + +// classifyError categorizes errors for targeted recovery strategies +func classifyError(err error) string { + if err == nil { + return "none" + } + + errMsg := err.Error() + + // Simple classification - in production, use more sophisticated logic + switch { + case contains(errMsg, "network", "timeout", "connection"): + return "network" + case contains(errMsg, "balance", "funds"): + return "insufficient_balance" + case contains(errMsg, "sign", "signature"): + return "signing_error" + case contains(errMsg, "invalid", "malformed"): + return "validation_error" + default: + return "unknown" + } +} + +// contains checks if the error message contains any of the keywords +func contains(msg string, keywords ...string) bool { + for _, keyword := range keywords { + if len(msg) > 0 && len(keyword) > 0 { + // Simple substring check - in production use better matching + for i := 0; i <= len(msg)-len(keyword); i++ { + if msg[i:i+len(keyword)] == keyword { + return true + } + } + } + } + return false +} + diff --git a/examples/go/clients/advanced/go.mod b/examples/go/clients/advanced/go.mod new file mode 100644 index 000000000..226e95836 --- /dev/null +++ b/examples/go/clients/advanced/go.mod @@ -0,0 +1,29 @@ +module github.com/coinbase/x402/examples/go/clients/advanced + +go 1.24.0 + +toolchain go1.24.1 + +replace github.com/coinbase/x402/go => ../../../../go + +require ( + github.com/coinbase/x402/go v0.0.0-00010101000000-000000000000 + github.com/joho/godotenv v1.5.1 +) + +require ( + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect +) diff --git a/examples/go/clients/advanced/hooks.go b/examples/go/clients/advanced/hooks.go new file mode 100644 index 000000000..d4a0c7e8e --- /dev/null +++ b/examples/go/clients/advanced/hooks.go @@ -0,0 +1,112 @@ +package main + +import ( + "context" + "fmt" + "net/http" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" +) + +/** + * Hooks Example + * + * This demonstrates how to register hooks for payment creation lifecycle events. + * Hooks allow you to add custom logic at different stages: + * - OnBeforePaymentCreation: Called before payment creation starts, can abort + * - OnAfterPaymentCreation: Called after successful payment creation + * - OnPaymentCreationFailure: Called when payment creation fails, can recover + * + * This is an advanced feature useful for: + * - Logging payment events for debugging and monitoring + * - Custom validation before allowing payments + * - Error recovery strategies + * - Metrics and analytics collection + */ + +func runHooksExample(ctx context.Context, evmPrivateKey, url string) error { + fmt.Println("🔧 Creating client with payment lifecycle hooks...\n") + + // Create signer from private key + evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(evmPrivateKey) + if err != nil { + return err + } + + // Create client with scheme registration + client := x402.Newx402Client(). + Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + + // Register lifecycle hooks + + // OnBeforePaymentCreation: Called before payment is created + // Use this for logging, validation, or aborting payment creation + client.OnBeforePaymentCreation(func(ctx x402.PaymentCreationContext) (*x402.BeforePaymentCreationHookResult, error) { + fmt.Printf("🔍 [BeforePaymentCreation] Creating payment for:\n") + fmt.Printf(" Network: %s\n", ctx.SelectedRequirements.GetNetwork()) + fmt.Printf(" Scheme: %s\n", ctx.SelectedRequirements.GetScheme()) + fmt.Println() + + // You can abort payment creation by returning: + // return &x402.BeforePaymentCreationHookResult{ + // Abort: true, + // Reason: "Payment not allowed for this resource", + // }, nil + + return nil, nil // Continue with payment creation + }) + + // OnAfterPaymentCreation: Called after payment is successfully created + // Use this for logging, metrics, or other side effects + client.OnAfterPaymentCreation(func(ctx x402.PaymentCreatedContext) error { + fmt.Printf("✅ [AfterPaymentCreation] Payment created successfully\n") + fmt.Printf(" Version: %d\n", ctx.Version) + fmt.Println() + + // Perform side effects like logging to database, sending metrics, etc. + // Errors here are logged but don't fail the payment + + return nil + }) + + // OnPaymentCreationFailure: Called when payment creation fails + // Use this for error recovery or alternative payment methods + client.OnPaymentCreationFailure(func(ctx x402.PaymentCreationFailureContext) (*x402.PaymentCreationFailureHookResult, error) { + fmt.Printf("❌ [OnPaymentCreationFailure] Payment creation failed: %v\n", ctx.Error) + fmt.Println() + + // You could attempt to recover by providing an alternative payload: + // return &x402.PaymentCreationFailureHookResult{ + // Recovered: true, + // Payload: alternativePayload, + // }, nil + + return nil, nil // Don't recover, let it fail + }) + + // Create HTTP client wrapper + httpClient := x402http.Newx402HTTPClient(client) + wrappedClient := x402http.WrapHTTPClientWithPayment(http.DefaultClient, httpClient) + + // Make request to trigger hooks + fmt.Printf("🌐 Making request to: %s\n\n", url) + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return err + } + + resp, err := wrappedClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + fmt.Println("✅ Request completed successfully with hooks\n") + + return printResponse(resp, "Response with hooks") +} + diff --git a/examples/go/clients/advanced/main.go b/examples/go/clients/advanced/main.go new file mode 100644 index 000000000..5690b7056 --- /dev/null +++ b/examples/go/clients/advanced/main.go @@ -0,0 +1,109 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "os" + "time" + + "github.com/joho/godotenv" +) + +/** + * Advanced Client Examples + * + * This package demonstrates advanced patterns for production-ready x402 clients: + * + * - custom-transport: Custom HTTP transport with retry logic and circuit breaker + * - error-recovery: Advanced error handling and automatic recovery strategies + * - multi-network-priority: Network selection with priority and fallback + * - hooks: Payment lifecycle hooks for custom logic at different stages + * + * Usage: + * go run . custom-transport + * go run . error-recovery + * go run . multi-network-priority + * go run . hooks + */ + +func main() { + // Load .env file if it exists + if err := godotenv.Load(); err != nil { + fmt.Println("No .env file found, using environment variables") + } + + pattern := "custom-transport" + if len(os.Args) > 1 { + pattern = os.Args[1] + } + + fmt.Printf("\n🚀 Running advanced example: %s\n\n", pattern) + + // Get configuration + evmPrivateKey := os.Getenv("EVM_PRIVATE_KEY") + if evmPrivateKey == "" { + fmt.Println("❌ EVM_PRIVATE_KEY environment variable is required") + os.Exit(1) + } + + url := os.Getenv("SERVER_URL") + if url == "" { + url = "http://localhost:4021/weather" + } + + // Run the selected example + ctx := context.Background() + + switch pattern { + case "custom-transport": + if err := runCustomTransportExample(ctx, evmPrivateKey, url); err != nil { + fmt.Printf("❌ Error: %v\n", err) + os.Exit(1) + } + + case "error-recovery": + if err := runErrorRecoveryExample(ctx, evmPrivateKey, url); err != nil { + fmt.Printf("❌ Error: %v\n", err) + os.Exit(1) + } + + case "multi-network-priority": + if err := runMultiNetworkPriorityExample(ctx, evmPrivateKey, url); err != nil { + fmt.Printf("❌ Error: %v\n", err) + os.Exit(1) + } + + case "hooks": + if err := runHooksExample(ctx, evmPrivateKey, url); err != nil { + fmt.Printf("❌ Error: %v\n", err) + os.Exit(1) + } + + default: + fmt.Printf("❌ Unknown pattern: %s\n", pattern) + fmt.Println("Available patterns: custom-transport, error-recovery, multi-network-priority, hooks") + os.Exit(1) + } +} + +// printResponse is a helper to display response data +func printResponse(resp *http.Response, label string) error { + var data interface{} + if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { + return err + } + + fmt.Printf("✅ %s:\n", label) + pretty, _ := json.MarshalIndent(data, " ", " ") + fmt.Printf(" %s\n\n", string(pretty)) + + return nil +} + +// printDuration prints elapsed time for an operation +func printDuration(start time.Time, label string) { + fmt.Printf("⏱️ %s took %v\n\n", label, time.Since(start)) +} + diff --git a/examples/go/clients/advanced/multi_network_priority.go b/examples/go/clients/advanced/multi_network_priority.go new file mode 100644 index 000000000..b3cb6e1c3 --- /dev/null +++ b/examples/go/clients/advanced/multi_network_priority.go @@ -0,0 +1,116 @@ +package main + +import ( + "context" + "fmt" + "net/http" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" +) + +/** + * Multi-Network Priority Example + * + * This example demonstrates how to configure network-specific signers + * with priority and fallback logic: + * - Specific networks get dedicated signers + * - Wildcard registration for fallback + * - Network-specific configuration + * - Demonstrating registration precedence + */ + +func runMultiNetworkPriorityExample(ctx context.Context, evmPrivateKey, url string) error { + fmt.Println("🌐 Configuring multi-network client with priority...\n") + + // Create primary signer (for most networks) + primarySigner, err := evmsigners.NewClientSignerFromPrivateKey(evmPrivateKey) + if err != nil { + return err + } + + // In a real scenario, you might have different signers for different networks + // For demo purposes, we'll use the same signer but show the pattern + mainnetSigner := primarySigner // Would be different in production + testnetSigner := primarySigner // Would be different in production + baseSigner := primarySigner // Would be different in production + + fmt.Println("📝 Registering networks with priority:") + fmt.Println(" 1. Specific networks (highest priority)") + fmt.Println(" 2. Network category wildcards") + fmt.Println(" 3. Global wildcard (lowest priority/fallback)\n") + + // Create client with prioritized network registration + // More specific registrations take precedence over wildcards + client := x402.Newx402Client() + + // Level 1: Specific networks (highest priority) + fmt.Println("✅ Registering Ethereum Mainnet (eip155:1) with mainnet signer") + client.Register("eip155:1", evm.NewExactEvmScheme(mainnetSigner)) + + fmt.Println("✅ Registering Base Mainnet (eip155:8453) with base signer") + client.Register("eip155:8453", evm.NewExactEvmScheme(baseSigner)) + + fmt.Println("✅ Registering Base Sepolia (eip155:84532) with testnet signer") + client.Register("eip155:84532", evm.NewExactEvmScheme(testnetSigner)) + + // Level 2: Wildcard for all other EVM networks (fallback) + fmt.Println("✅ Registering all other EVM networks (eip155:*) with primary signer\n") + client.Register("eip155:*", evm.NewExactEvmScheme(primarySigner)) + + // Add logging to show which network is being used + client.OnBeforePaymentCreation(func(ctx x402.PaymentCreationContext) (*x402.BeforePaymentCreationHookResult, error) { + fmt.Printf("💰 Creating payment for network: %s\n", ctx.SelectedRequirements.GetNetwork()) + fmt.Printf(" Scheme: %s\n", ctx.SelectedRequirements.GetScheme()) + + // Show which signer would be used based on network + var signerType string + switch ctx.SelectedRequirements.GetNetwork() { + case "eip155:1": + signerType = "Mainnet-specific signer" + case "eip155:8453": + signerType = "Base-specific signer" + case "eip155:84532": + signerType = "Testnet-specific signer" + default: + signerType = "Fallback signer (wildcard)" + } + fmt.Printf(" Using: %s\n\n", signerType) + + return nil, nil + }) + + // Wrap HTTP client + httpClient := x402http.Newx402HTTPClient(client) + wrappedClient := x402http.WrapHTTPClientWithPayment(http.DefaultClient, httpClient) + + // Make request + fmt.Printf("🌐 Making request to: %s\n", url) + fmt.Println(" (Server will determine which network to use)\n") + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return err + } + + resp, err := wrappedClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + fmt.Println("\n📋 Network Priority Configuration:") + fmt.Println(" Priority 1: eip155:1 (Ethereum Mainnet) → mainnet signer") + fmt.Println(" Priority 2: eip155:8453 (Base Mainnet) → base signer") + fmt.Println(" Priority 3: eip155:84532 (Base Sepolia) → testnet signer") + fmt.Println(" Priority 4: eip155:* (All others) → primary signer\n") + + fmt.Println("ℹ️ More specific registrations always override wildcards") + fmt.Println(" This allows fine-grained control per network while having") + fmt.Println(" sensible defaults for unknown networks.\n") + + return printResponse(resp, "Response with multi-network priority") +} + diff --git a/examples/go/clients/custom/.env-example b/examples/go/clients/custom/.env-example new file mode 100644 index 000000000..066c1bc2b --- /dev/null +++ b/examples/go/clients/custom/.env-example @@ -0,0 +1,3 @@ +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= +SERVER_URL=http://localhost:4021/weather diff --git a/examples/go/clients/custom/.gitignore b/examples/go/clients/custom/.gitignore new file mode 100644 index 000000000..b6617f14a --- /dev/null +++ b/examples/go/clients/custom/.gitignore @@ -0,0 +1,25 @@ +# Environment variables +.env + +# Binaries +*.exe +*.exe~ +*.dll +*.so +*.dylib +custom +client +main + +# Go build artifacts +*.test +*.out +go.sum + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + diff --git a/examples/go/clients/custom/README.md b/examples/go/clients/custom/README.md new file mode 100644 index 000000000..0e1b8f060 --- /dev/null +++ b/examples/go/clients/custom/README.md @@ -0,0 +1,176 @@ +# Custom x402 Client Implementation + +Example client demonstrating how to implement x402 payment handling manually using only the core packages, without convenience wrappers like `x402http.WrapHTTPClientWithPayment`. + +## Prerequisites + +- Go 1.24 or higher +- Valid EVM private key for making payments +- A running x402 server (see [server examples](../../servers/)) + +## Setup + +1. Copy `.env-example` to `.env`: + +```bash +cp .env-example .env +``` + +and fill required environment variables: + +- `EVM_PRIVATE_KEY` - Ethereum private key for EVM payments +- `SERVER_URL` - Server endpoint (defaults to `http://localhost:4021/weather`) + +2. Install dependencies: + +```bash +go mod download +``` + +3. Run the example: + +```bash +go run . +``` + +## Testing the Example + +Start a server first: + +```bash +cd ../../servers/gin +go run main.go +``` + +Then run the custom client: + +```bash +cd ../../clients/custom +go run . +``` + +## HTTP Headers (v2 Protocol) + +| Header | Direction | Description | +| ------------------- | --------------- | -------------------------------------- | +| `PAYMENT-REQUIRED` | Server → Client | 402 response with payment requirements | +| `PAYMENT-SIGNATURE` | Client → Server | Retry request with payment payload | +| `PAYMENT-RESPONSE` | Server → Client | 200 response with settlement details | + +## Payment Flow + +1. **Initial Request** — Make HTTP request to protected endpoint +2. **402 Response** — Server responds with requirements in `PAYMENT-REQUIRED` header +3. **Parse Requirements** — Decode requirements using version detection +4. **Create Payment** — Use `x402Client.CreatePaymentPayload()` to generate payload +5. **Encode Payment** — Base64 encode the payload for the header value +6. **Retry with Payment** — Make new request with `PAYMENT-SIGNATURE` header +7. **Success** — Receive 200 with settlement in `PAYMENT-RESPONSE` header + +## Key Implementation Details + +### 1. Setting Up the Client + +```go +import ( + x402 "github.com/coinbase/x402/go" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" +) + +evmSigner, _ := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY")) + +client := x402.Newx402Client(). + Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) +``` + +### 2. Detecting Payment Required + +```go +resp, _ := http.DefaultClient.Do(req) + +if resp.StatusCode == http.StatusPaymentRequired { + // Extract PAYMENT-REQUIRED header + headerValue := resp.Header.Get("PAYMENT-REQUIRED") + decoded, _ := base64.StdEncoding.DecodeString(headerValue) + + var paymentRequired types.PaymentRequired + json.Unmarshal(decoded, &paymentRequired) + // paymentRequired.Accepts contains the payment options +} +``` + +### 3. Creating Payment Payload + +```go +// Select first payment requirement +requirements := paymentRequired.Accepts[0] + +// Create payment payload using the x402 client +payload, _ := x402Client.CreatePaymentPayload(ctx, requirements, + paymentRequired.Resource, paymentRequired.Extensions) + +payloadBytes, _ := json.Marshal(payload) +encodedPayment := base64.StdEncoding.EncodeToString(payloadBytes) +``` + +### 4. Retrying with Payment + +```go +retryReq, _ := http.NewRequestWithContext(ctx, "GET", url, nil) +retryReq.Header.Set("PAYMENT-SIGNATURE", encodedPayment) + +retryResp, _ := http.DefaultClient.Do(retryReq) +``` + +### 5. Extracting Settlement + +```go +settlementHeader := resp.Header.Get("PAYMENT-RESPONSE") +decoded, _ := base64.StdEncoding.DecodeString(settlementHeader) + +var settlement x402.SettleResponse +json.Unmarshal(decoded, &settlement) +// settlement.Transaction, settlement.Network, settlement.Payer +``` + +## Wrapper vs Custom Comparison + +| Aspect | With Wrapper (x402http) | Custom Implementation | +| ----------------- | ----------------------- | --------------------- | +| Code Complexity | ~10 lines | ~250 lines | +| Automatic Retry | ✅ Yes | ❌ Manual | +| Error Handling | ✅ Built-in | ❌ You implement | +| Header Management | ✅ Automatic | ❌ Manual | +| Flexibility | Limited | ✅ Complete control | + +## When to Use Custom Implementation + +- Need complete control over every step of the payment flow +- Integrating with non-standard HTTP libraries (Resty, Fiber, etc.) +- Implementing custom retry/error logic +- Learning how x402 works under the hood +- Building adapters for unsupported frameworks + +## Protocol Versions + +The example handles both v1 and v2 protocols: + +**V2 Protocol (recommended):** +- Payment requirements in `PAYMENT-REQUIRED` header +- Payment signature in `PAYMENT-SIGNATURE` header + +**V1 Protocol (legacy):** +- Payment requirements in response body with `x402Version: 1` +- Payment signature in `X-PAYMENT` header + +## Next Steps + +- **[Basic HTTP Client](../http/)** — See the simple wrapper approach +- **[Server Examples](../../servers/)** — Build servers that accept payments + +## Related Resources + +- [x402 Go Package Documentation](../../../../go/) +- [HTTP Client Package](../../../../go/http/) +- [Payment Types](../../../../go/types/) diff --git a/examples/go/clients/custom/go.mod b/examples/go/clients/custom/go.mod new file mode 100644 index 000000000..2094f91a8 --- /dev/null +++ b/examples/go/clients/custom/go.mod @@ -0,0 +1,29 @@ +module github.com/coinbase/x402/examples/go/clients/custom + +go 1.24.0 + +toolchain go1.24.1 + +replace github.com/coinbase/x402/go => ../../../../go + +require ( + github.com/coinbase/x402/go v0.0.0-00010101000000-000000000000 + github.com/joho/godotenv v1.5.1 +) + +require ( + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect +) diff --git a/examples/go/clients/custom/main.go b/examples/go/clients/custom/main.go new file mode 100644 index 000000000..ee28bf451 --- /dev/null +++ b/examples/go/clients/custom/main.go @@ -0,0 +1,381 @@ +package main + +import ( + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "strings" + "time" + + x402 "github.com/coinbase/x402/go" + "github.com/coinbase/x402/go/types" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" + "github.com/joho/godotenv" +) + +/** + * Custom Client Implementation - Direct x402 Integration + * + * This example demonstrates how to implement x402 payment handling manually + * WITHOUT using the pre-built HTTP client wrapper. It shows the implementation + * details of how to handle 402 responses and create payments directly. + * + * This is useful when you: + * - Want to understand how x402 works under the hood + * - Need to integrate with a custom HTTP client or framework + * - Want full control over the payment flow + * - Are building a custom transport layer + * + * The flow: + * 1. Make initial HTTP request + * 2. Detect 402 Payment Required response + * 3. Extract payment requirements from response + * 4. Create payment using x402 core package + * 5. Retry request with payment header + * 6. Handle successful response + */ + +func main() { + // Load .env file if it exists + if err := godotenv.Load(); err != nil { + fmt.Println("No .env file found, using environment variables") + } + + // Get configuration + evmPrivateKey := os.Getenv("EVM_PRIVATE_KEY") + if evmPrivateKey == "" { + fmt.Println("❌ EVM_PRIVATE_KEY environment variable is required") + os.Exit(1) + } + + url := os.Getenv("SERVER_URL") + if url == "" { + url = "http://localhost:4021/weather" + } + + // Create context + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // Create x402 client (core package) + evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(evmPrivateKey) + if err != nil { + fmt.Printf("❌ Failed to create signer: %v\n", err) + os.Exit(1) + } + + x402Client := x402.Newx402Client(). + Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + + // Make the request with custom payment handling + fmt.Println("🔧 Using custom payment implementation (no wrapper)\n") + + resp, err := makeRequestWithPayment(ctx, x402Client, url) + if err != nil { + fmt.Printf("❌ Request failed: %v\n", err) + os.Exit(1) + } + defer resp.Body.Close() + + // Read and display response + var responseData interface{} + if err := json.NewDecoder(resp.Body).Decode(&responseData); err != nil { + fmt.Printf("❌ Failed to decode response: %v\n", err) + os.Exit(1) + } + + fmt.Println("\n✅ Response body:") + prettyJSON, _ := json.MarshalIndent(responseData, " ", " ") + fmt.Printf(" %s\n", string(prettyJSON)) + + // Extract payment settlement details + if paymentHeader := resp.Header.Get("PAYMENT-RESPONSE"); paymentHeader != "" { + settleResp, err := extractSettlementResponse(paymentHeader) + if err == nil { + fmt.Println("\n💰 Payment Settlement Details:") + fmt.Printf(" Transaction: %s\n", settleResp.Transaction) + fmt.Printf(" Network: %s\n", settleResp.Network) + fmt.Printf(" Payer: %s\n", settleResp.Payer) + } + } +} + +// makeRequestWithPayment implements the complete payment flow manually +func makeRequestWithPayment(ctx context.Context, x402Client *x402.X402Client, url string) (*http.Response, error) { + // ======================================================================== + // Step 1: Make initial request + // ======================================================================== + fmt.Println("📤 Step 1: Making initial request...") + fmt.Printf(" URL: %s\n\n", url) + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return nil, fmt.Errorf("failed to create request: %w", err) + } + + client := &http.Client{Timeout: 30 * time.Second} + resp, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("request failed: %w", err) + } + + // ======================================================================== + // Step 2: Check if payment is required + // ======================================================================== + if resp.StatusCode != http.StatusPaymentRequired { + fmt.Printf("✅ Step 2: No payment required (status: %d)\n", resp.StatusCode) + return resp, nil + } + + fmt.Println("💳 Step 2: Payment required (402 response)") + defer resp.Body.Close() + + // ======================================================================== + // Step 3: Extract payment requirements + // ======================================================================== + fmt.Println("🔍 Step 3: Extracting payment requirements...") + + // Read response headers and body + headers := extractHeaders(resp.Header) + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("failed to read response body: %w", err) + } + + // Detect which protocol version (v1 or v2) + version, err := detectVersion(headers, body) + if err != nil { + return nil, fmt.Errorf("failed to detect payment version: %w", err) + } + + fmt.Printf(" Detected protocol version: v%d\n", version) + + // Extract payment requirements based on version + var paymentRequirements types.PaymentRequirements + var resource *types.ResourceInfo + var extensions map[string]interface{} + + if version == 2 { + paymentRequirements, resource, extensions, err = extractV2Requirements(headers, body) + } else { + paymentRequirements, err = extractV1Requirements(body) + } + + if err != nil { + return nil, fmt.Errorf("failed to extract payment requirements: %w", err) + } + + fmt.Printf(" Network: %s\n", paymentRequirements.Network) + fmt.Printf(" Scheme: %s\n", paymentRequirements.Scheme) + fmt.Printf(" Amount: %+v\n\n", paymentRequirements.Amount) + + // ======================================================================== + // Step 4: Create payment payload + // ======================================================================== + fmt.Println("💰 Step 4: Creating payment payload...") + + var payloadBytes []byte + if version == 2 { + // V2 payment creation + payload, err := x402Client.CreatePaymentPayload(ctx, paymentRequirements, resource, extensions) + if err != nil { + return nil, fmt.Errorf("failed to create V2 payment: %w", err) + } + payloadBytes, err = json.Marshal(payload) + if err != nil { + return nil, fmt.Errorf("failed to marshal V2 payload: %w", err) + } + } else { + // V1 payment creation + requirementsV1 := types.PaymentRequirementsV1{ + Scheme: paymentRequirements.Scheme, + Network: paymentRequirements.Network, + PayTo: paymentRequirements.PayTo, + MaxAmountRequired: paymentRequirements.Amount, + Asset: paymentRequirements.Asset, + MaxTimeoutSeconds: paymentRequirements.MaxTimeoutSeconds, + } + payload, err := x402Client.CreatePaymentPayloadV1(ctx, requirementsV1) + if err != nil { + return nil, fmt.Errorf("failed to create V1 payment: %w", err) + } + payloadBytes, err = json.Marshal(payload) + if err != nil { + return nil, fmt.Errorf("failed to marshal V1 payload: %w", err) + } + } + + fmt.Printf(" Created payload: %d bytes\n\n", len(payloadBytes)) + + // ======================================================================== + // Step 5: Retry request with payment + // ======================================================================== + fmt.Println("🔄 Step 5: Retrying request with payment...") + + // Encode payment as base64 and add to header + encodedPayment := base64.StdEncoding.EncodeToString(payloadBytes) + + // Create new request with payment header + retryReq, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return nil, fmt.Errorf("failed to create retry request: %w", err) + } + + // Add payment header (v2 uses PAYMENT-SIGNATURE, v1 uses X-PAYMENT) + if version == 2 { + retryReq.Header.Set("PAYMENT-SIGNATURE", encodedPayment) + fmt.Println(" Added PAYMENT-SIGNATURE header") + } else { + retryReq.Header.Set("X-PAYMENT", encodedPayment) + fmt.Println(" Added X-PAYMENT header") + } + + // Make the retry request + retryResp, err := client.Do(retryReq) + if err != nil { + return nil, fmt.Errorf("retry request failed: %w", err) + } + + fmt.Printf(" Response status: %d\n", retryResp.StatusCode) + + // ======================================================================== + // Step 6: Verify success + // ======================================================================== + if retryResp.StatusCode >= 400 { + defer retryResp.Body.Close() + errorBody, _ := io.ReadAll(retryResp.Body) + return nil, fmt.Errorf("payment failed: status %d, body: %s", retryResp.StatusCode, string(errorBody)) + } + + fmt.Println("✅ Step 6: Payment successful!\n") + + return retryResp, nil +} + +// ============================================================================ +// Helper Functions for Manual Implementation +// ============================================================================ + +// extractHeaders converts http.Header to map[string]string +func extractHeaders(h http.Header) map[string]string { + headers := make(map[string]string) + for k, v := range h { + if len(v) > 0 { + headers[k] = v[0] + } + } + return headers +} + +// detectVersion detects whether the server is using v1 or v2 protocol +func detectVersion(headers map[string]string, body []byte) (int, error) { + // Normalize headers to uppercase for comparison + normalizedHeaders := make(map[string]string) + for k, v := range headers { + normalizedHeaders[strings.ToUpper(k)] = v + } + + // V2 uses PAYMENT-REQUIRED header + if _, exists := normalizedHeaders["PAYMENT-REQUIRED"]; exists { + return 2, nil + } + + // V1 uses body with x402Version field + if len(body) > 0 { + var versionCheck struct { + X402Version int `json:"x402Version"` + } + if err := json.Unmarshal(body, &versionCheck); err == nil { + if versionCheck.X402Version == 1 { + return 1, nil + } + } + } + + return 0, fmt.Errorf("could not detect x402 version from response") +} + +// extractV2Requirements extracts payment requirements from V2 response +func extractV2Requirements(headers map[string]string, body []byte) (types.PaymentRequirements, *types.ResourceInfo, map[string]interface{}, error) { + // Normalize headers + normalizedHeaders := make(map[string]string) + for k, v := range headers { + normalizedHeaders[strings.ToUpper(k)] = v + } + + // Get PAYMENT-REQUIRED header + headerValue, exists := normalizedHeaders["PAYMENT-REQUIRED"] + if !exists { + return types.PaymentRequirements{}, nil, nil, fmt.Errorf("PAYMENT-REQUIRED header not found") + } + + // Decode base64 header + decoded, err := base64.StdEncoding.DecodeString(headerValue) + if err != nil { + return types.PaymentRequirements{}, nil, nil, fmt.Errorf("invalid base64 encoding: %w", err) + } + + // Parse payment required structure + var paymentRequired types.PaymentRequired + if err := json.Unmarshal(decoded, &paymentRequired); err != nil { + return types.PaymentRequirements{}, nil, nil, fmt.Errorf("invalid payment required JSON: %w", err) + } + + // Select first acceptable payment requirement + // In a real implementation, you might want to choose based on preference + if len(paymentRequired.Accepts) == 0 { + return types.PaymentRequirements{}, nil, nil, fmt.Errorf("no payment requirements offered") + } + + selectedRequirement := paymentRequired.Accepts[0] + + return selectedRequirement, paymentRequired.Resource, paymentRequired.Extensions, nil +} + +// extractV1Requirements extracts payment requirements from V1 response body +func extractV1Requirements(body []byte) (types.PaymentRequirements, error) { + var paymentRequiredV1 types.PaymentRequiredV1 + if err := json.Unmarshal(body, &paymentRequiredV1); err != nil { + return types.PaymentRequirements{}, fmt.Errorf("invalid V1 payment required JSON: %w", err) + } + + // Select first acceptable payment requirement + if len(paymentRequiredV1.Accepts) == 0 { + return types.PaymentRequirements{}, fmt.Errorf("no payment requirements offered") + } + + selected := paymentRequiredV1.Accepts[0] + + // Convert V1 requirements to common format + return types.PaymentRequirements{ + Scheme: selected.Scheme, + Network: selected.Network, + PayTo: selected.PayTo, + Amount: selected.MaxAmountRequired, + Asset: selected.Asset, + MaxTimeoutSeconds: selected.MaxTimeoutSeconds, + }, nil +} + +// extractSettlementResponse extracts settlement details from response header +func extractSettlementResponse(headerValue string) (x402.SettleResponse, error) { + // Decode base64 header + decoded, err := base64.StdEncoding.DecodeString(headerValue) + if err != nil { + return x402.SettleResponse{}, fmt.Errorf("invalid base64 encoding: %w", err) + } + + // Parse settlement response + var settleResp x402.SettleResponse + if err := json.Unmarshal(decoded, &settleResp); err != nil { + return x402.SettleResponse{}, fmt.Errorf("invalid settlement response JSON: %w", err) + } + + return settleResp, nil +} + diff --git a/examples/go/clients/http/.env-example b/examples/go/clients/http/.env-example new file mode 100644 index 000000000..066c1bc2b --- /dev/null +++ b/examples/go/clients/http/.env-example @@ -0,0 +1,3 @@ +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= +SERVER_URL=http://localhost:4021/weather diff --git a/examples/go/clients/http/.gitignore b/examples/go/clients/http/.gitignore new file mode 100644 index 000000000..84df09b0c --- /dev/null +++ b/examples/go/clients/http/.gitignore @@ -0,0 +1,25 @@ +# Environment variables +.env + +# Binaries +*.exe +*.exe~ +*.dll +*.so +*.dylib +http +client +main + +# Go build artifacts +*.test +*.out +go.sum + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + diff --git a/examples/go/clients/http/README.md b/examples/go/clients/http/README.md new file mode 100644 index 000000000..a4d065771 --- /dev/null +++ b/examples/go/clients/http/README.md @@ -0,0 +1,187 @@ +# x402-http Example Client + +Example client demonstrating how to use the x402 Go HTTP client to make requests to endpoints protected by the x402 payment protocol. + +## Prerequisites + +- Go 1.24 or higher +- A running x402 server (see [gin server example](../../servers/gin)) +- Valid EVM and/or SVM private keys for making payments + +## Setup + +1. Install dependencies: +```bash +go mod download +``` + +2. Copy `.env-example` to `.env` and add your private keys: +```bash +cp .env-example .env +``` + +Required environment variables: +- `EVM_PRIVATE_KEY` - Ethereum private key for EVM payments +- `SVM_PRIVATE_KEY` - Solana private key for SVM payments (optional) +- `SERVER_URL` - Server endpoint (defaults to `http://localhost:4021/weather`) + +**⚠️ Security Warning:** Never use mainnet keys in `.env` files! Use testnet keys only. + +3. Run the client: +```bash +go run . +``` + +## Available Examples + +### 1. Builder Pattern (`builder-pattern`) + +Configure the client by chaining `.Register()` calls to map network patterns to scheme clients. + +```bash +go run . builder-pattern +``` + +### 2. Mechanism Helper Registration (`mechanism-helper-registration`) + +Use mechanism helpers with wildcard network registration for clean, simple configuration. + +```bash +go run . mechanism-helper-registration +``` + +## Example Code + +```go +import ( + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" +) + +// Create signer +signer, err := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY")) + +// Configure client with builder pattern +client := x402.Newx402Client(). + Register("eip155:*", evm.NewExactEvmScheme(signer)) + +// Wrap HTTP client with payment handling +httpClient := x402http.WrapHTTPClientWithPayment( + http.DefaultClient, + x402http.Newx402HTTPClient(client), +) + +// Make request to paid endpoint (payment is handled automatically) +resp, err := httpClient.Get("http://localhost:4021/weather") +body, _ := io.ReadAll(resp.Body) +fmt.Println(string(body)) +``` + +## Example Output + +``` +Running example: builder-pattern + +Making request to: http://localhost:4021/weather + +✅ Response body: + { + "city": "San Francisco", + "weather": "foggy", + "temperature": 60, + "timestamp": "2024-01-01T00:00:00Z" + } + +💰 Payment Details: + Transaction: 0x1234567890abcdef... + Network: eip155:84532 + Payer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +``` + +## Network Registration + +**Network identifiers** use [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) format: +- `eip155:84532` — Base Sepolia +- `eip155:8453` — Base Mainnet +- `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` — Solana Devnet +- `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` — Solana Mainnet + +### Wildcard Registration + +Register all networks of a type with a single signer: + +```go +client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) +client.Register("solana:*", svm.NewExactSvmScheme(svmSigner)) +``` + +### Specific Network Registration + +Register specific networks with different signers: + +```go +client. + Register("eip155:*", evm.NewExactEvmScheme(defaultSigner)). // Fallback for all EVM + Register("eip155:1", evm.NewExactEvmScheme(mainnetSigner)) // Override for Ethereum Mainnet +``` + +More specific registrations take precedence over wildcards. + +## Private Key Management + +### Creating Signers + +Use the signer helpers for easy key management: + +```go +// EVM signer from hex private key (with or without 0x prefix) +evmSigner, err := evmsigners.NewClientSignerFromPrivateKey("0x1234...") + +// SVM signer from base58 private key +svmSigner, err := svmsigners.NewClientSignerFromPrivateKey("5J7W...") + +// From environment variable +evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY")) +``` + +### Generating Test Keys + +For testing, generate keys with these tools: + +**Ethereum:** +```bash +# Using cast (foundry) +cast wallet new +``` + +**Solana:** +```bash +# Using solana CLI +solana-keygen new +``` + +## Testing Against Local Server + +1. Start a local x402 server: +```bash +cd ../../servers/gin +go run main.go +``` + +2. Run the client in another terminal: +```bash +cd ../../clients/http +go run . builder-pattern +``` + +## Next Steps + +See [Advanced Examples](../advanced/) for custom transport, retry logic and error handling. + +## Related Resources + +- [x402 Go Package Documentation](../../../../go/) +- [Signer Helpers Documentation](../../../../go/signers/) +- [Server Examples](../../servers/) — build servers that can receive these payments diff --git a/examples/go/clients/http/builder_pattern.go b/examples/go/clients/http/builder_pattern.go new file mode 100644 index 000000000..ec9dd45dd --- /dev/null +++ b/examples/go/clients/http/builder_pattern.go @@ -0,0 +1,56 @@ +package main + +import ( + x402 "github.com/coinbase/x402/go" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + svm "github.com/coinbase/x402/go/mechanisms/svm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" + svmsigners "github.com/coinbase/x402/go/signers/svm" +) + +/** + * Builder Pattern Client + * + * This demonstrates the basic way to configure an x402 client by chaining + * Register() calls to map network patterns to scheme clients. + * + * This approach gives you fine-grained control over which networks use + * which signers and schemes. + */ + +func createBuilderPatternClient(evmPrivateKey, svmPrivateKey string) (*x402.X402Client, error) { + // Create signers from private keys + evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(evmPrivateKey) + if err != nil { + return nil, err + } + + // Create client and register schemes using builder pattern + client := x402.Newx402Client() + + // Register EVM scheme for all EVM networks + client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + + // You can also register specific networks for fine-grained control + // For example, use a different signer for Ethereum mainnet: + // ethereumSigner := evmsigners.NewClientSignerFromPrivateKey(ethereumKey) + // client.Register("eip155:1", evm.NewExactEvmScheme(ethereumSigner)) + + // Register SVM scheme if key is provided + if svmPrivateKey != "" { + svmSigner, err := svmsigners.NewClientSignerFromPrivateKey(svmPrivateKey) + if err != nil { + return nil, err + } + + // Register for all Solana networks + client.Register("solana:*", svm.NewExactSvmScheme(svmSigner)) + + // Could also register specific networks: + // client.Register("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", svm.NewExactSvmScheme(solanaMainnetSigner)) + // client.Register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", svm.NewExactSvmScheme(solanaDevnetSigner)) + } + + return client, nil +} + diff --git a/examples/go/clients/http/go.mod b/examples/go/clients/http/go.mod new file mode 100644 index 000000000..d694f2dd4 --- /dev/null +++ b/examples/go/clients/http/go.mod @@ -0,0 +1,56 @@ +module github.com/coinbase/x402/examples/go/clients/http + +go 1.24.0 + +toolchain go1.24.1 + +replace github.com/coinbase/x402/go => ../../../../go + +require ( + github.com/coinbase/x402/go v0.0.0-00010101000000-000000000000 + github.com/joho/godotenv v1.5.1 +) + +require ( + filippo.io/edwards25519 v1.0.0-rc.1 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/blendle/zapdriver v1.3.1 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/gagliardetto/binary v0.8.0 // indirect + github.com/gagliardetto/solana-go v1.14.0 // indirect + github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + go.mongodb.org/mongo-driver v1.12.2 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/ratelimit v0.2.0 // indirect + go.uber.org/zap v1.21.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/time v0.9.0 // indirect +) diff --git a/examples/go/clients/http/main.go b/examples/go/clients/http/main.go new file mode 100644 index 000000000..8eab6c344 --- /dev/null +++ b/examples/go/clients/http/main.go @@ -0,0 +1,132 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "os" + "time" + + x402 "github.com/coinbase/x402/go" + "github.com/joho/godotenv" +) + +/** + * Main example runner for Go HTTP client demonstrations. + * + * This example shows how to use the x402 Go HTTP client to make requests + * to resource servers that require payment. Different client creation + * patterns can be selected via CLI argument: + * + * - builder-pattern: Basic builder pattern with Register() + * - mechanism-helper-registration: Using mechanism helpers for clean registration + * + * Usage: + * go run . builder-pattern + * go run . mechanism-helper-registration + */ + +func main() { + // Load .env file if it exists + if err := godotenv.Load(); err != nil { + fmt.Println("No .env file found, using environment variables") + } + + pattern := "builder-pattern" + if len(os.Args) > 1 { + pattern = os.Args[1] + } + + fmt.Printf("\nRunning example: %s\n\n", pattern) + + // Get configuration + evmPrivateKey := os.Getenv("EVM_PRIVATE_KEY") + if evmPrivateKey == "" { + fmt.Println("❌ EVM_PRIVATE_KEY environment variable is required") + os.Exit(1) + } + + svmPrivateKey := os.Getenv("SVM_PRIVATE_KEY") + + url := os.Getenv("SERVER_URL") + if url == "" { + url = "http://localhost:4021/weather" + } + + // Create client based on pattern + var client *x402.X402Client + var err error + + switch pattern { + case "builder-pattern": + client, err = createBuilderPatternClient(evmPrivateKey, svmPrivateKey) + case "mechanism-helper-registration": + client, err = createMechanismHelperRegistrationClient(evmPrivateKey, svmPrivateKey) + default: + fmt.Printf("❌ Unknown pattern: %s\n", pattern) + fmt.Println("Available patterns: builder-pattern, mechanism-helper-registration") + os.Exit(1) + } + + if err != nil { + fmt.Printf("❌ Failed to create client: %v\n", err) + os.Exit(1) + } + + // Make the request + if err := makeRequest(client, url); err != nil { + fmt.Printf("❌ Request failed: %v\n", err) + os.Exit(1) + } +} + +// makeRequest performs an HTTP GET request with payment handling +func makeRequest(client *x402.X402Client, url string) error { + httpClient := wrapHTTPClient(client) + + fmt.Printf("Making request to: %s\n\n", url) + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return fmt.Errorf("failed to create request: %w", err) + } + + resp, err := httpClient.Do(req) + if err != nil { + return fmt.Errorf("request failed: %w", err) + } + defer resp.Body.Close() + + // Read response body + var responseData interface{} + if err := json.NewDecoder(resp.Body).Decode(&responseData); err != nil { + return fmt.Errorf("failed to decode response: %w", err) + } + + fmt.Println("✅ Response body:") + prettyJSON, _ := json.MarshalIndent(responseData, " ", " ") + fmt.Printf(" %s\n", string(prettyJSON)) + + // Extract payment response from headers if present + paymentHeader := resp.Header.Get("PAYMENT-RESPONSE") + if paymentHeader == "" { + paymentHeader = resp.Header.Get("X-PAYMENT-RESPONSE") + } + + if paymentHeader != "" { + fmt.Println("\n💰 Payment Details:") + settleResp, err := extractPaymentResponse(resp.Header) + if err == nil { + fmt.Printf(" Transaction: %s\n", settleResp.Transaction) + fmt.Printf(" Network: %s\n", settleResp.Network) + fmt.Printf(" Payer: %s\n", settleResp.Payer) + } + } + + return nil +} + diff --git a/examples/go/clients/http/mechanism_helper_registration.go b/examples/go/clients/http/mechanism_helper_registration.go new file mode 100644 index 000000000..cf4d79b40 --- /dev/null +++ b/examples/go/clients/http/mechanism_helper_registration.go @@ -0,0 +1,56 @@ +package main + +import ( + x402 "github.com/coinbase/x402/go" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + svm "github.com/coinbase/x402/go/mechanisms/svm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" + svmsigners "github.com/coinbase/x402/go/signers/svm" +) + +/** + * Mechanism Helper Registration Client + * + * This demonstrates a convenient pattern using mechanism helpers with wildcard + * network registration for clean, readable client configuration. + * + * This approach is simpler than the builder pattern when you want to register + * all networks of a particular type with the same signer. + */ + +func createMechanismHelperRegistrationClient(evmPrivateKey, svmPrivateKey string) (*x402.X402Client, error) { + // Create signers from private keys + evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(evmPrivateKey) + if err != nil { + return nil, err + } + + // Start with a new client + client := x402.Newx402Client() + + // Register EVM scheme for all EVM networks using wildcard + // This registers: + // - eip155:* (all EVM networks in v2) + client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + + // Register SVM scheme if key is provided + if svmPrivateKey != "" { + svmSigner, err := svmsigners.NewClientSignerFromPrivateKey(svmPrivateKey) + if err != nil { + return nil, err + } + + // Register for all Solana networks using wildcard + // This registers: + // - solana:* (all Solana networks in v2) + client.Register("solana:*", svm.NewExactSvmScheme(svmSigner)) + } + + // The fluent API allows chaining for clean code: + // client := x402.Newx402Client(). + // Register("eip155:*", evm.NewExactEvmScheme(evmSigner)). + // Register("solana:*", svm.NewExactSvmScheme(svmSigner)) + + return client, nil +} + diff --git a/examples/go/clients/http/utils.go b/examples/go/clients/http/utils.go new file mode 100644 index 000000000..6a004f8ae --- /dev/null +++ b/examples/go/clients/http/utils.go @@ -0,0 +1,48 @@ +package main + +import ( + "encoding/base64" + "encoding/json" + "net/http" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" +) + +// wrapHTTPClient wraps a standard HTTP client with x402 payment handling +func wrapHTTPClient(x402Client *x402.X402Client) *http.Client { + // Create x402 HTTP client wrapper + httpClient := x402http.Newx402HTTPClient(x402Client) + + // Wrap standard HTTP client with payment handling + return x402http.WrapHTTPClientWithPayment(http.DefaultClient, httpClient) +} + +// extractPaymentResponse extracts settlement details from response headers +func extractPaymentResponse(headers http.Header) (*x402.SettleResponse, error) { + // Try v2 header first + paymentHeader := headers.Get("PAYMENT-RESPONSE") + if paymentHeader == "" { + // Try v1 header + paymentHeader = headers.Get("X-PAYMENT-RESPONSE") + } + + if paymentHeader == "" { + return nil, nil + } + + // Decode base64 + decoded, err := base64.StdEncoding.DecodeString(paymentHeader) + if err != nil { + return nil, err + } + + // Parse settlement response + var settleResp x402.SettleResponse + if err := json.Unmarshal(decoded, &settleResp); err != nil { + return nil, err + } + + return &settleResp, nil +} + diff --git a/examples/go/facilitator/.env-example b/examples/go/facilitator/.env-example new file mode 100644 index 000000000..8bca99e73 --- /dev/null +++ b/examples/go/facilitator/.env-example @@ -0,0 +1,2 @@ +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= diff --git a/examples/go/facilitator/.gitignore b/examples/go/facilitator/.gitignore new file mode 100644 index 000000000..764ebff13 --- /dev/null +++ b/examples/go/facilitator/.gitignore @@ -0,0 +1,24 @@ +# Environment variables +.env + +# Binaries +*.exe +*.exe~ +*.dll +*.so +*.dylib +facilitator +main + +# Go build artifacts +*.test +*.out +go.sum + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + diff --git a/examples/go/facilitator/README.md b/examples/go/facilitator/README.md new file mode 100644 index 000000000..d9b24e57c --- /dev/null +++ b/examples/go/facilitator/README.md @@ -0,0 +1,301 @@ +# x402 Facilitator Example + +This example demonstrates how to build a simple x402 facilitator that verifies and settles payments on behalf of clients. + +## What is a Facilitator? + +A **facilitator** is a service that acts as a payment processor in the x402 protocol: + +1. **Verifies** payment signatures from clients +2. **Settles** payments by submitting transactions to the blockchain +3. **Returns** confirmation to clients + +Facilitators allow clients to create payments without needing to interact with the blockchain directly, making it easier to build payment-enabled applications. + +## What This Example Shows + +- **Basic Facilitator Setup**: Creating and configuring a facilitator +- **Payment Verification**: Verifying client payment signatures with idiomatic error handling +- **On-chain Settlement**: Submitting transactions to the blockchain (EVM + SVM) +- **Facilitator Signer Implementation**: See `signer.go` for EVM and SVM signer examples +- **Lifecycle Hooks**: Logging verification and settlement operations +- **HTTP Endpoints**: Exposing /verify, /settle, and /supported APIs + +## Files in This Example + +- **`main.go`** - Main facilitator server with hooks and endpoints +- **`signer.go`** - Facilitator signer implementations for EVM and SVM +- **`README.md`** - This file + +## Architecture + +``` +Client → Resource Server → Facilitator → Blockchain + │ │ │ │ + │ │ │ │ + │ 1. Request resource │ │ + │ 2. Return 402 Payment Required │ + │ │ │ + │ 3. Create payment │ │ + │ 4. Request w/ payment │ │ + │ │ │ │ + │ │ 5. Verify → │ + │ │ ← Valid │ │ + │ │ │ │ + │ 6. Return resource │ │ + │ │ │ │ + │ │ 7. Settle → 8. Submit tx → + │ │ ← Success ← ← Confirmed +``` + +## Signer Implementation + +The `signer.go` file contains reference implementations for EVM and SVM facilitator signers that handle: +- EIP-712 signature verification +- Transaction submission and confirmation +- Balance checking +- RPC client management + +For production deployments with additional features (Bazaar discovery, multiple networks), see `e2e/facilitators/go/main.go`. + +## Prerequisites + +- Go 1.21 or higher +- EVM private key with Base Sepolia ETH for transaction fees +- SVM private key with Solana Devnet SOL for transaction fees (optional) + +## Setup + +1. Create a `.env` file: + +```bash +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= +``` + +**⚠️ Security Note:** The facilitator private key needs ETH/SOL for gas fees. Use a dedicated testnet account. + +2. Install dependencies and run: + +```bash +go mod download +go run . +``` + +## Error Handling + +The facilitator SDK uses **idiomatic Go error handling** with custom error types: + +**Success Pattern:** +```go +result, err := facilitator.Verify(ctx, payload, requirements) +if err != nil { + return err // Any failure (business logic or system) +} +// result.IsValid is guaranteed to be true +``` + +**Structured Error Information:** +```go +result, err := facilitator.Verify(ctx, payload, requirements) +if err != nil { + // Extract structured error details if needed + if ve, ok := err.(*x402.VerifyError); ok { + log.Printf("Verification failed: reason=%s, payer=%s, network=%s", + ve.Reason, ve.Payer, ve.Network) + } + return err +} +``` + +**Error Types:** +- `*VerifyError` - Verification failures with `Reason`, `Payer`, `Network`, `Err` +- `*SettleError` - Settlement failures with `Reason`, `Payer`, `Network`, `Transaction`, `Err` + +This replaces the old pattern of checking both `err != nil` and `response.IsValid == false`. + +## API Endpoints + +### GET /supported + +Returns supported networks and schemes. + +**Response:** +```json +{ + "kinds": [ + { + "x402Version": 2, + "scheme": "exact", + "network": "eip155:84532" + }, + { + "x402Version": 2, + "scheme": "exact", + "network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" + } + ] +} +``` + +### POST /verify + +Verifies a payment signature. + +**Request:** +```json +{ + "paymentPayload": { + "x402Version": 2, + "resource": { + "url": "http://localhost:4021/weather", + "description": "Weather data", + "mimeType": "application/json" + }, + "accepted": { + "scheme": "exact", + "network": "eip155:84532", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "amount": "1000", + "payTo": "0x...", + "maxTimeoutSeconds": 300, + "extra": { "name": "USDC", "version": "2" } + }, + "payload": { + "signature": "0x...", + "authorization": { "from": "0x...", "to": "0x...", "value": "1000", "..." : "..." } + } + }, + "paymentRequirements": { + "scheme": "exact", + "network": "eip155:84532", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "amount": "1000", + "payTo": "0x...", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2" + } + } +} +``` + +Response (success): + +```json +{ + "isValid": true, + "payer": "0x..." +} +``` + +Response (failure): + +```json +{ + "isValid": false, + "invalidReason": "invalid_signature" +} +``` + +### POST /settle + +Settles a verified payment by broadcasting the transaction on-chain. + +Request body is identical to `/verify`. + +Response (success): + +```json +{ + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x..." +} +``` + +Response (failure): + +```json +{ + "success": false, + "errorReason": "insufficient_balance", + "transaction": "", + "network": "eip155:84532" +} +``` + +## Extending the Example + +### Adding Networks + +Register additional schemes for other networks: + +```go +import ( + x402 "github.com/coinbase/x402/go" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/facilitator" + svm "github.com/coinbase/x402/go/mechanisms/svm/exact/facilitator" +) + +facilitator := x402.Newx402Facilitator() + +// Register EVM scheme with smart wallet deployment enabled +evmConfig := &evm.ExactEvmSchemeConfig{ + DeployERC4337WithEIP6492: true, +} +facilitator.Register([]x402.Network{"eip155:84532"}, evm.NewExactEvmScheme(evmSigner, evmConfig)) + +// Register SVM scheme +facilitator.Register([]x402.Network{"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"}, svm.NewExactSvmScheme(svmSigner)) +``` + +### Lifecycle Hooks + +Add custom logic before/after verify and settle operations: + +```go +facilitator := x402.Newx402Facilitator() + +facilitator.OnBeforeVerify(func(ctx x402.FacilitatorVerifyContext) (*x402.FacilitatorBeforeHookResult, error) { + // Log or validate before verification + return nil, nil +}) + +facilitator.OnAfterVerify(func(ctx x402.FacilitatorVerifyResultContext) error { + // Track verified payments + return nil +}) + +facilitator.OnVerifyFailure(func(ctx x402.FacilitatorVerifyFailureContext) (*x402.FacilitatorVerifyFailureHookResult, error) { + // Handle verification failures + return nil, nil +}) + +facilitator.OnBeforeSettle(func(ctx x402.FacilitatorSettleContext) (*x402.FacilitatorBeforeHookResult, error) { + // Validate before settlement + // Return &x402.FacilitatorBeforeHookResult{Abort: true, Reason: "..."} to cancel + return nil, nil +}) + +facilitator.OnAfterSettle(func(ctx x402.FacilitatorSettleResultContext) error { + // Track successful settlements + return nil +}) + +facilitator.OnSettleFailure(func(ctx x402.FacilitatorSettleFailureContext) (*x402.FacilitatorSettleFailureHookResult, error) { + // Handle settlement failures + return nil, nil +}) +``` + +## Network Identifiers + +Networks use [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) format: + +- `eip155:84532` — Base Sepolia +- `eip155:8453` — Base Mainnet +- `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` — Solana Devnet +- `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` — Solana Mainnet diff --git a/examples/go/facilitator/go.mod b/examples/go/facilitator/go.mod new file mode 100644 index 000000000..a29773602 --- /dev/null +++ b/examples/go/facilitator/go.mod @@ -0,0 +1,88 @@ +module github.com/coinbase/x402/examples/go/facilitator + +go 1.24.0 + +toolchain go1.24.1 + +replace github.com/coinbase/x402/go => ../../../go + +require ( + github.com/coinbase/x402/go v0.0.0-00010101000000-000000000000 + github.com/ethereum/go-ethereum v1.16.7 + github.com/gagliardetto/solana-go v1.14.0 + github.com/gin-gonic/gin v1.11.0 + github.com/joho/godotenv v1.5.1 +) + +require ( + filippo.io/edwards25519 v1.0.0-rc.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/blendle/zapdriver v1.3.1 // indirect + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gagliardetto/binary v0.8.0 // indirect + github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.27.0 // indirect + github.com/goccy/go-json v0.10.4 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.55.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + go.mongodb.org/mongo-driver v1.12.2 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/ratelimit v0.2.0 // indirect + go.uber.org/zap v1.21.0 // indirect + golang.org/x/arch v0.20.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/time v0.9.0 // indirect + golang.org/x/tools v0.36.0 // indirect + google.golang.org/protobuf v1.36.9 // indirect +) diff --git a/examples/go/facilitator/main.go b/examples/go/facilitator/main.go new file mode 100644 index 000000000..589373b23 --- /dev/null +++ b/examples/go/facilitator/main.go @@ -0,0 +1,167 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "os" + "time" + + x402 "github.com/coinbase/x402/go" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/facilitator" + evmv1 "github.com/coinbase/x402/go/mechanisms/evm/exact/v1/facilitator" + svm "github.com/coinbase/x402/go/mechanisms/svm/exact/facilitator" + svmv1 "github.com/coinbase/x402/go/mechanisms/svm/exact/v1/facilitator" + "github.com/gin-gonic/gin" + "github.com/joho/godotenv" +) + +const ( + DefaultPort = "4022" +) + +func main() { + godotenv.Load() + + evmPrivateKey := os.Getenv("EVM_PRIVATE_KEY") + if evmPrivateKey == "" { + fmt.Println("❌ EVM_PRIVATE_KEY environment variable is required") + os.Exit(1) + } + + svmPrivateKey := os.Getenv("SVM_PRIVATE_KEY") + + evmNetwork := x402.Network("eip155:84532") + svmNetwork := x402.Network("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") + + evmSigner, err := newFacilitatorEvmSigner(evmPrivateKey, DefaultEvmRPC) + if err != nil { + fmt.Printf("❌ Failed to create EVM signer: %v\n", err) + os.Exit(1) + } + + var svmSigner *facilitatorSvmSigner + if svmPrivateKey != "" { + svmSigner, _ = newFacilitatorSvmSigner(svmPrivateKey, DefaultSvmRPC) + } + + facilitator := x402.Newx402Facilitator() + + // Register V2 EVM scheme with smart wallet deployment enabled + evmConfig := &evm.ExactEvmSchemeConfig{ + DeployERC4337WithEIP6492: true, + } + facilitator.Register([]x402.Network{evmNetwork}, evm.NewExactEvmScheme(evmSigner, evmConfig)) + + // Register V1 EVM scheme with smart wallet deployment enabled + evmV1Config := &evmv1.ExactEvmSchemeV1Config{ + DeployERC4337WithEIP6492: true, + } + facilitator.RegisterV1([]x402.Network{"base-sepolia"}, evmv1.NewExactEvmSchemeV1(evmSigner, evmV1Config)) + + if svmSigner != nil { + facilitator.Register([]x402.Network{svmNetwork}, svm.NewExactSvmScheme(svmSigner)) + facilitator.RegisterV1([]x402.Network{"solana-devnet"}, svmv1.NewExactSvmSchemeV1(svmSigner)) + } + + facilitator.OnAfterVerify(func(ctx x402.FacilitatorVerifyResultContext) error { + fmt.Printf("✅ Payment verified\n") + return nil + }) + + facilitator.OnAfterSettle(func(ctx x402.FacilitatorSettleResultContext) error { + fmt.Printf("🎉 Payment settled: %s\n", ctx.Result.Transaction) + return nil + }) + + gin.SetMode(gin.ReleaseMode) + r := gin.New() + r.Use(gin.Recovery()) + + // Supported endpoint - returns supported networks and schemes + r.GET("/supported", func(c *gin.Context) { + // Get supported kinds - networks already registered + supported := facilitator.GetSupported() + c.JSON(http.StatusOK, supported) + }) + + // Verify endpoint - verifies payment signatures + r.POST("/verify", func(c *gin.Context) { + ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) + defer cancel() + + // Read request body + var reqBody struct { + PaymentPayload json.RawMessage `json:"paymentPayload"` + PaymentRequirements json.RawMessage `json:"paymentRequirements"` + } + + if err := c.BindJSON(&reqBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"}) + return + } + + // Verify payment + result, err := facilitator.Verify(ctx, reqBody.PaymentPayload, reqBody.PaymentRequirements) + if err != nil { + // All failures (business logic and system errors) are returned as errors + // You can extract structured information from VerifyError if needed: + // if ve, ok := err.(*x402.VerifyError); ok { + // log.Printf("Verification failed: reason=%s, payer=%s, network=%s", + // ve.Reason, ve.Payer, ve.Network) + // } + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + // Success! result.IsValid is guaranteed to be true + c.JSON(http.StatusOK, result) + }) + + // Settle endpoint - settles payments on-chain + r.POST("/settle", func(c *gin.Context) { + ctx, cancel := context.WithTimeout(c.Request.Context(), 60*time.Second) + defer cancel() + + // Read request body + var reqBody struct { + PaymentPayload json.RawMessage `json:"paymentPayload"` + PaymentRequirements json.RawMessage `json:"paymentRequirements"` + } + + if err := c.BindJSON(&reqBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"}) + return + } + + // Settle payment + result, err := facilitator.Settle(ctx, reqBody.PaymentPayload, reqBody.PaymentRequirements) + if err != nil { + // All failures (business logic and system errors) are returned as errors + // You can extract structured information from SettleError if needed: + // if se, ok := err.(*x402.SettleError); ok { + // log.Printf("Settlement failed: reason=%s, payer=%s, network=%s, tx=%s", + // se.Reason, se.Payer, se.Network, se.Transaction) + // } + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + // Success! result.Success is guaranteed to be true + c.JSON(http.StatusOK, result) + }) + + fmt.Printf("🚀 Facilitator listening on http://localhost:%s\n", DefaultPort) + fmt.Printf(" EVM: %s on %s\n", evmSigner.GetAddresses()[0], evmNetwork) + if svmSigner != nil { + fmt.Printf(" SVM: %s on %s\n", svmSigner.GetAddresses(context.Background(), string(svmNetwork))[0], svmNetwork) + } + fmt.Println() + + if err := r.Run(":" + DefaultPort); err != nil { + fmt.Printf("Error starting server: %v\n", err) + os.Exit(1) + } +} + diff --git a/examples/go/facilitator/signer.go b/examples/go/facilitator/signer.go new file mode 100644 index 000000000..19f57d085 --- /dev/null +++ b/examples/go/facilitator/signer.go @@ -0,0 +1,609 @@ +package main + +import ( + "bytes" + "context" + "crypto/ecdsa" + "fmt" + "math/big" + "strings" + "time" + + evmmech "github.com/coinbase/x402/go/mechanisms/evm" + svmmech "github.com/coinbase/x402/go/mechanisms/svm" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/signer/core/apitypes" + solana "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" +) + +const ( + DefaultEvmRPC = "https://sepolia.base.org" + DefaultSvmRPC = "https://api.devnet.solana.com" +) + +// ============================================================================ +// EVM Facilitator Signer +// ============================================================================ + +// facilitatorEvmSigner implements the FacilitatorEvmSigner interface +type facilitatorEvmSigner struct { + privateKey *ecdsa.PrivateKey + address common.Address + client *ethclient.Client + chainID *big.Int +} + +// newFacilitatorEvmSigner creates a new EVM facilitator signer +// +// Args: +// +// privateKeyHex: Private key in hex format (with or without 0x prefix) +// rpcURL: RPC endpoint URL +// +// Returns: +// +// *facilitatorEvmSigner or error +func newFacilitatorEvmSigner(privateKeyHex string, rpcURL string) (*facilitatorEvmSigner, error) { + // Remove 0x prefix if present + privateKeyHex = strings.TrimPrefix(privateKeyHex, "0x") + + privateKey, err := crypto.HexToECDSA(privateKeyHex) + if err != nil { + return nil, fmt.Errorf("failed to parse private key: %w", err) + } + + address := crypto.PubkeyToAddress(privateKey.PublicKey) + + // Connect to blockchain + client, err := ethclient.Dial(rpcURL) + if err != nil { + return nil, fmt.Errorf("failed to connect to RPC: %w", err) + } + + // Get chain ID + ctx := context.Background() + chainID, err := client.ChainID(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get chain ID: %w", err) + } + + return &facilitatorEvmSigner{ + privateKey: privateKey, + address: address, + client: client, + chainID: chainID, + }, nil +} + +func (s *facilitatorEvmSigner) GetAddresses() []string { + return []string{s.address.Hex()} +} + +func (s *facilitatorEvmSigner) GetChainID(ctx context.Context) (*big.Int, error) { + return s.chainID, nil +} + +func (s *facilitatorEvmSigner) VerifyTypedData( + ctx context.Context, + address string, + domain evmmech.TypedDataDomain, + types map[string][]evmmech.TypedDataField, + primaryType string, + message map[string]interface{}, + signature []byte, +) (bool, error) { + // Convert to apitypes for EIP-712 verification + chainId := getBigIntFromInterface(domain.ChainID) + typedData := apitypes.TypedData{ + Types: make(apitypes.Types), + PrimaryType: primaryType, + Domain: apitypes.TypedDataDomain{ + Name: getStringFromInterface(domain.Name), + Version: getStringFromInterface(domain.Version), + ChainId: (*math.HexOrDecimal256)(chainId), + VerifyingContract: getStringFromInterface(domain.VerifyingContract), + }, + Message: message, + } + + // Convert types + for typeName, fields := range types { + typedFields := make([]apitypes.Type, len(fields)) + for i, field := range fields { + typedFields[i] = apitypes.Type{ + Name: field.Name, + Type: field.Type, + } + } + typedData.Types[typeName] = typedFields + } + + // Add EIP712Domain if not present + if _, exists := typedData.Types["EIP712Domain"]; !exists { + typedData.Types["EIP712Domain"] = []apitypes.Type{ + {Name: "name", Type: "string"}, + {Name: "version", Type: "string"}, + {Name: "chainId", Type: "uint256"}, + {Name: "verifyingContract", Type: "address"}, + } + } + + // Hash the data + dataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message) + if err != nil { + return false, fmt.Errorf("failed to hash struct: %w", err) + } + + domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map()) + if err != nil { + return false, fmt.Errorf("failed to hash domain: %w", err) + } + + rawData := []byte{0x19, 0x01} + rawData = append(rawData, domainSeparator...) + rawData = append(rawData, dataHash...) + digest := crypto.Keccak256(rawData) + + // Recover the address from signature + if len(signature) != 65 { + return false, fmt.Errorf("invalid signature length: %d", len(signature)) + } + + // Adjust v value + v := signature[64] + if v >= 27 { + v -= 27 + } + + sigCopy := make([]byte, 65) + copy(sigCopy, signature) + sigCopy[64] = v + + pubKey, err := crypto.SigToPub(digest, sigCopy) + if err != nil { + return false, fmt.Errorf("failed to recover public key: %w", err) + } + + recoveredAddr := crypto.PubkeyToAddress(*pubKey) + expectedAddr := common.HexToAddress(address) + + return bytes.Equal(recoveredAddr.Bytes(), expectedAddr.Bytes()), nil +} + +func (s *facilitatorEvmSigner) ReadContract( + ctx context.Context, + contractAddress string, + abiJSON []byte, + method string, + args ...interface{}, +) (interface{}, error) { + // Parse ABI + contractABI, err := abi.JSON(strings.NewReader(string(abiJSON))) + if err != nil { + return nil, fmt.Errorf("failed to parse ABI: %w", err) + } + + // Pack the method call + data, err := contractABI.Pack(method, args...) + if err != nil { + return nil, fmt.Errorf("failed to pack method call: %w", err) + } + + // Make the call + to := common.HexToAddress(contractAddress) + + msg := ethereum.CallMsg{ + To: &to, + Data: data, + } + + result, err := s.client.CallContract(ctx, msg, nil) + if err != nil { + return nil, fmt.Errorf("failed to call contract: %w", err) + } + + // Handle empty result + if len(result) == 0 { + if method == "authorizationState" { + return false, nil + } + if method == "balanceOf" || method == "allowance" { + return big.NewInt(0), nil + } + return nil, fmt.Errorf("empty result from contract call") + } + + // Unpack the result + methodObj, exists := contractABI.Methods[method] + if !exists { + return nil, fmt.Errorf("method %s not found in ABI", method) + } + + output, err := methodObj.Outputs.Unpack(result) + if err != nil { + return nil, fmt.Errorf("failed to unpack result: %w", err) + } + + if len(output) > 0 { + return output[0], nil + } + + return nil, nil +} + +func (s *facilitatorEvmSigner) WriteContract( + ctx context.Context, + contractAddress string, + abiJSON []byte, + method string, + args ...interface{}, +) (string, error) { + // Parse ABI + contractABI, err := abi.JSON(strings.NewReader(string(abiJSON))) + if err != nil { + return "", fmt.Errorf("failed to parse ABI: %w", err) + } + + // Pack the method call + data, err := contractABI.Pack(method, args...) + if err != nil { + return "", fmt.Errorf("failed to pack method call: %w", err) + } + + // Get nonce + nonce, err := s.client.PendingNonceAt(ctx, s.address) + if err != nil { + return "", fmt.Errorf("failed to get nonce: %w", err) + } + + // Get gas price + gasPrice, err := s.client.SuggestGasPrice(ctx) + if err != nil { + return "", fmt.Errorf("failed to get gas price: %w", err) + } + + // Create transaction + to := common.HexToAddress(contractAddress) + tx := types.NewTransaction( + nonce, + to, + big.NewInt(0), // value + 300000, // gas limit + gasPrice, + data, + ) + + // Sign transaction + signedTx, err := types.SignTx(tx, types.LatestSignerForChainID(s.chainID), s.privateKey) + if err != nil { + return "", fmt.Errorf("failed to sign transaction: %w", err) + } + + // Send transaction + err = s.client.SendTransaction(ctx, signedTx) + if err != nil { + return "", fmt.Errorf("failed to send transaction: %w", err) + } + + return signedTx.Hash().Hex(), nil +} + +func (s *facilitatorEvmSigner) SendTransaction( + ctx context.Context, + to string, + data []byte, +) (string, error) { + // Get nonce + nonce, err := s.client.PendingNonceAt(ctx, s.address) + if err != nil { + return "", fmt.Errorf("failed to get nonce: %w", err) + } + + // Get gas price + gasPrice, err := s.client.SuggestGasPrice(ctx) + if err != nil { + return "", fmt.Errorf("failed to get gas price: %w", err) + } + + // Create transaction with raw data + toAddr := common.HexToAddress(to) + tx := types.NewTransaction( + nonce, + toAddr, + big.NewInt(0), // value + 300000, // gas limit + gasPrice, + data, + ) + + // Sign transaction + signedTx, err := types.SignTx(tx, types.LatestSignerForChainID(s.chainID), s.privateKey) + if err != nil { + return "", fmt.Errorf("failed to sign transaction: %w", err) + } + + // Send transaction + err = s.client.SendTransaction(ctx, signedTx) + if err != nil { + return "", fmt.Errorf("failed to send transaction: %w", err) + } + + return signedTx.Hash().Hex(), nil +} + +func (s *facilitatorEvmSigner) WaitForTransactionReceipt(ctx context.Context, txHash string) (*evmmech.TransactionReceipt, error) { + hash := common.HexToHash(txHash) + + // Poll for receipt + for i := 0; i < 30; i++ { // 30 seconds timeout + receipt, err := s.client.TransactionReceipt(ctx, hash) + if err == nil && receipt != nil { + return &evmmech.TransactionReceipt{ + Status: uint64(receipt.Status), + BlockNumber: receipt.BlockNumber.Uint64(), + TxHash: receipt.TxHash.Hex(), + }, nil + } + time.Sleep(1 * time.Second) + } + + return nil, fmt.Errorf("transaction receipt not found after 30 seconds") +} + +func (s *facilitatorEvmSigner) GetBalance(ctx context.Context, address string, tokenAddress string) (*big.Int, error) { + if tokenAddress == "" || tokenAddress == "0x0000000000000000000000000000000000000000" { + // Native balance + balance, err := s.client.BalanceAt(ctx, common.HexToAddress(address), nil) + if err != nil { + return nil, fmt.Errorf("failed to get balance: %w", err) + } + return balance, nil + } + + // ERC20 balance + const erc20ABI = `[{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"}]` + + result, err := s.ReadContract(ctx, tokenAddress, []byte(erc20ABI), "balanceOf", common.HexToAddress(address)) + if err != nil { + return nil, err + } + + if balance, ok := result.(*big.Int); ok { + return balance, nil + } + + return nil, fmt.Errorf("unexpected balance type: %T", result) +} + +func (s *facilitatorEvmSigner) GetCode(ctx context.Context, address string) ([]byte, error) { + addr := common.HexToAddress(address) + code, err := s.client.CodeAt(ctx, addr, nil) + if err != nil { + return nil, fmt.Errorf("failed to get code: %w", err) + } + return code, nil +} + +// ============================================================================ +// SVM (Solana) Facilitator Signer +// ============================================================================ + +// facilitatorSvmSigner implements the FacilitatorSvmSigner interface +type facilitatorSvmSigner struct { + privateKey solana.PrivateKey + rpcClients map[string]*rpc.Client + rpcURL string +} + +// newFacilitatorSvmSigner creates a new SVM facilitator signer +// +// Args: +// +// privateKeyBase58: Private key in base58 format +// rpcURL: RPC endpoint URL (empty string uses network default) +// +// Returns: +// +// *facilitatorSvmSigner or error +func newFacilitatorSvmSigner(privateKeyBase58 string, rpcURL string) (*facilitatorSvmSigner, error) { + privateKey, err := solana.PrivateKeyFromBase58(privateKeyBase58) + if err != nil { + return nil, fmt.Errorf("failed to parse Solana private key: %w", err) + } + + return &facilitatorSvmSigner{ + privateKey: privateKey, + rpcClients: make(map[string]*rpc.Client), + rpcURL: rpcURL, + }, nil +} + +// getRPC is a private helper method to get RPC client for a network +func (s *facilitatorSvmSigner) getRPC(ctx context.Context, network string) (*rpc.Client, error) { + if client, ok := s.rpcClients[network]; ok { + return client, nil + } + + rpcURL := s.rpcURL + if rpcURL == "" { + config, err := svmmech.GetNetworkConfig(network) + if err != nil { + return nil, err + } + rpcURL = config.RPCURL + } + + client := rpc.New(rpcURL) + s.rpcClients[network] = client + return client, nil +} + +func (s *facilitatorSvmSigner) SignTransaction(ctx context.Context, tx *solana.Transaction, feePayer solana.PublicKey, network string) error { + // Verify feePayer matches our key + if feePayer != s.privateKey.PublicKey() { + return fmt.Errorf("no signer for feePayer %s. Available: %s", feePayer, s.privateKey.PublicKey()) + } + + messageBytes, err := tx.Message.MarshalBinary() + if err != nil { + return fmt.Errorf("failed to marshal message: %w", err) + } + + signature, err := s.privateKey.Sign(messageBytes) + if err != nil { + return fmt.Errorf("failed to sign: %w", err) + } + + accountIndex, err := tx.GetAccountIndex(s.privateKey.PublicKey()) + if err != nil { + return fmt.Errorf("failed to get account index: %w", err) + } + + if len(tx.Signatures) <= int(accountIndex) { + newSignatures := make([]solana.Signature, accountIndex+1) + copy(newSignatures, tx.Signatures) + tx.Signatures = newSignatures + } + + tx.Signatures[accountIndex] = signature + return nil +} + +func (s *facilitatorSvmSigner) SimulateTransaction(ctx context.Context, tx *solana.Transaction, network string) error { + rpcClient, err := s.getRPC(ctx, network) + if err != nil { + return err + } + + opts := rpc.SimulateTransactionOpts{ + SigVerify: true, + ReplaceRecentBlockhash: false, + Commitment: svmmech.DefaultCommitment, + } + + simResult, err := rpcClient.SimulateTransactionWithOpts(ctx, tx, &opts) + if err != nil { + return fmt.Errorf("simulation failed: %w", err) + } + + if simResult != nil && simResult.Value != nil && simResult.Value.Err != nil { + return fmt.Errorf("simulation failed: transaction would fail on-chain") + } + + return nil +} + +func (s *facilitatorSvmSigner) SendTransaction(ctx context.Context, tx *solana.Transaction, network string) (solana.Signature, error) { + rpcClient, err := s.getRPC(ctx, network) + if err != nil { + return solana.Signature{}, err + } + + sig, err := rpcClient.SendTransactionWithOpts(ctx, tx, rpc.TransactionOpts{ + SkipPreflight: true, + PreflightCommitment: svmmech.DefaultCommitment, + }) + if err != nil { + return solana.Signature{}, fmt.Errorf("failed to send transaction: %w", err) + } + + return sig, nil +} + +func (s *facilitatorSvmSigner) ConfirmTransaction(ctx context.Context, signature solana.Signature, network string) error { + rpcClient, err := s.getRPC(ctx, network) + if err != nil { + return err + } + + for attempt := 0; attempt < svmmech.MaxConfirmAttempts; attempt++ { + // Check for context cancellation + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + // Try getSignatureStatuses first (faster) + statuses, err := rpcClient.GetSignatureStatuses(ctx, true, signature) + if err == nil && statuses != nil && statuses.Value != nil && len(statuses.Value) > 0 { + status := statuses.Value[0] + if status != nil { + if status.Err != nil { + return fmt.Errorf("transaction failed on-chain") + } + if status.ConfirmationStatus == rpc.ConfirmationStatusConfirmed || + status.ConfirmationStatus == rpc.ConfirmationStatusFinalized { + return nil + } + } + } + + // Fallback to getTransaction + if err != nil { + txResult, txErr := rpcClient.GetTransaction(ctx, signature, &rpc.GetTransactionOpts{ + Encoding: solana.EncodingBase58, + Commitment: svmmech.DefaultCommitment, + }) + + if txErr == nil && txResult != nil && txResult.Meta != nil { + if txResult.Meta.Err != nil { + return fmt.Errorf("transaction failed on-chain") + } + return nil + } + } + + // Wait before retrying + time.Sleep(svmmech.ConfirmRetryDelay) + } + + return fmt.Errorf("transaction confirmation timed out after %d attempts", svmmech.MaxConfirmAttempts) +} + +func (s *facilitatorSvmSigner) GetAddresses(ctx context.Context, network string) []solana.PublicKey { + return []solana.PublicKey{s.privateKey.PublicKey()} +} + +// ============================================================================ +// Helper Functions +// ============================================================================ + +func getStringFromInterface(v interface{}) string { + if v == nil { + return "" + } + switch val := v.(type) { + case string: + return val + case *string: + if val != nil { + return *val + } + } + return "" +} + +func getBigIntFromInterface(v interface{}) *big.Int { + if v == nil { + return big.NewInt(0) + } + switch val := v.(type) { + case *big.Int: + return val + case int64: + return big.NewInt(val) + case string: + n, _ := new(big.Int).SetString(val, 10) + return n + } + return big.NewInt(0) +} + diff --git a/examples/go/servers/advanced/.env-example b/examples/go/servers/advanced/.env-example new file mode 100644 index 000000000..7e5cdfcaf --- /dev/null +++ b/examples/go/servers/advanced/.env-example @@ -0,0 +1,3 @@ +EVM_PAYEE_ADDRESS= +SVM_PAYEE_ADDRESS= +FACILITATOR_URL= diff --git a/examples/go/servers/advanced/.gitignore b/examples/go/servers/advanced/.gitignore new file mode 100644 index 000000000..3a5600b2e --- /dev/null +++ b/examples/go/servers/advanced/.gitignore @@ -0,0 +1,27 @@ +# Environment variables +.env + +# Binaries +*.exe +*.exe~ +*.dll +*.so +*.dylib +bazaar +dynamic-pay-to +dynamic-price +custom-money-definition +hooks + +# Go build artifacts +*.test +*.out +go.sum + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + diff --git a/examples/go/servers/advanced/README.md b/examples/go/servers/advanced/README.md new file mode 100644 index 000000000..cd04d9ee0 --- /dev/null +++ b/examples/go/servers/advanced/README.md @@ -0,0 +1,304 @@ +# x402-gin Advanced Examples + +Gin server demonstrating advanced x402 patterns including dynamic pricing, payment routing, lifecycle hooks and API discoverability. + +## Prerequisites + +- Go 1.21 or higher +- Valid EVM address for receiving payments +- URL of a facilitator supporting the desired payment network, see [facilitator list](https://www.x402.org/ecosystem?category=facilitators) + +## Setup + +1. Copy `.env-example` to `.env`: + +```bash +cp .env-example .env +``` + +and fill required environment variables: + +- `FACILITATOR_URL` - Facilitator endpoint URL +- `EVM_PAYEE_ADDRESS` - Ethereum address to receive payments + +2. Install dependencies: + +```bash +go mod download +``` + +3. Run an example (each example is standalone): + +```bash +go run hooks.go +``` + +## Available Examples + +Each example demonstrates a specific advanced pattern: + +| Example | Command | Description | +| --- | --- | --- | +| `bazaar` | `go run bazaar.go` | API discoverability via Bazaar | +| `hooks` | `go run hooks.go` | Payment lifecycle hooks | +| `dynamic-price` | `go run dynamic-price.go` | Context-based pricing | +| `dynamic-pay-to` | `go run dynamic-pay-to.go` | Route payments to different recipients | +| `custom-money-definition` | `go run custom-money-definition.go` | Accept alternative tokens | + +## Testing the Server + +You can test the server using one of the example clients: + +### Using the Go Client + +```bash +cd ../../clients/custom +# Ensure .env is setup +go run main.go +``` + +## Example: Bazaar Discovery + +Adding the discovery extension to make your API discoverable: + +```go +discoveryExtension, err := bazaar.DeclareDiscoveryExtension( + bazaar.MethodGET, + map[string]interface{}{"city": "San Francisco"}, + types.JSONSchema{ + "properties": map[string]interface{}{ + "city": map[string]interface{}{ + "type": "string", + "description": "City name to get weather for", + }, + }, + "required": []string{"city"}, + }, + "", + &types.OutputConfig{ + Example: map[string]interface{}{ + "city": "San Francisco", "weather": "foggy", "temperature": 60, + }, + }, +) + +routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.001", + Network: evmNetwork, + Description: "Weather data", + MimeType: "application/json", + Extensions: map[string]interface{}{ + types.BAZAAR: discoveryExtension, + }, + }, +} +``` + +**Use case:** Clients and AI agents can easily discover your service + +## Example: Dynamic Pricing + +Calculate prices at runtime based on request context: + +```go +dynamicPrice := func(ctx context.Context, reqCtx x402http.HTTPRequestContext) (x402.Price, error) { + tier := "standard" // Extract from request context + if tier == "premium" { + return "$0.005", nil // Premium tier: 0.5 cents + } + return "$0.001", nil // Standard tier: 0.1 cents +} + +routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: x402http.DynamicPriceFunc(dynamicPrice), + Network: evmNetwork, + }, +} +``` + +**Use case:** Implementing tiered pricing, user-based pricing, content-based pricing or any scenario where the price varies based on the request. + +## Example: Dynamic PayTo + +Route payments to different recipients based on request context: + +```go +addressLookup := map[string]string{ + "US": "0x...", + "UK": "0x...", +} + +dynamicPayTo := func(ctx context.Context, reqCtx x402http.HTTPRequestContext) (string, error) { + country := "US" // Extract from request context + address, ok := addressLookup[country] + if !ok { + address = defaultAddress + } + return address, nil +} + +routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: x402http.DynamicPayToFunc(dynamicPayTo), + Price: "$0.001", + Network: evmNetwork, + }, +} +``` + +**Use case:** Marketplace applications where payments should go to different sellers, content creators, or service providers based on the resource being accessed. + +## Example: Lifecycle Hooks + +Run custom logic before/after verification and settlement: + +```go +server := x402http.NewServer(routes, x402.WithFacilitatorClient(facilitatorClient)) +server.Register(evmNetwork, evm.NewExactEvmScheme()) + +server.OnBeforeVerify(func(ctx x402.VerifyContext) (*x402.BeforeHookResult, error) { + fmt.Println("Before verify hook", ctx) + // Abort verification by returning &x402.BeforeHookResult{Abort: true, Reason: "..."} + return nil, nil +}) + +server.OnAfterSettle(func(ctx x402.SettleResultContext) error { + // Log payment to database + db.RecordTransaction(ctx.Result.Transaction, ctx.Result.Payer) + return nil +}) + +server.OnSettleFailure(func(ctx x402.SettleFailureContext) (*x402.SettleFailureHookResult, error) { + // Return a result with Recovered=true to recover from the failure + // return &x402.SettleFailureHookResult{Recovered: true, Result: &x402.SettleResponse{...}} + return nil, nil +}) +``` + +Available hooks: + +- `OnBeforeVerify` — Run before verification (can abort) +- `OnAfterVerify` — Run after successful verification +- `OnVerifyFailure` — Run when verification fails (can recover) +- `OnBeforeSettle` — Run before settlement (can abort) +- `OnAfterSettle` — Run after successful settlement +- `OnSettleFailure` — Run when settlement fails (can recover) + +**Use case:** + +- Log payment events to a database or monitoring system +- Perform custom validation before processing payments +- Implement retry or recovery logic for failed payments +- Trigger side effects (notifications, database updates) after successful payments + +## Example: Custom Tokens + +Accept payments in custom tokens. Register a money parser on the scheme to support alternative tokens for specific networks. + +```go +evmScheme := evm.NewExactEvmScheme().RegisterMoneyParser( + func(amount float64, network x402.Network) (*x402.AssetAmount, error) { + // Use Wrapped XDAI on Gnosis Chain + if string(network) == "eip155:100" { + return &x402.AssetAmount{ + Amount: fmt.Sprintf("%.0f", amount*1e18), + Asset: "0xe91d153e0b41518a2ce8dd3d7944fa863463a97d", + Extra: map[string]interface{}{"token": "Wrapped XDAI"}, + }, nil + } + return nil, nil // Fall through to default parser + }, +) + +r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: evmNetwork, Server: evmScheme}, + }, +})) +``` + +**Use case:** When you want to accept payments in tokens other than USDC, or use different tokens based on conditions (e.g., DAI for large amounts, custom tokens for specific networks). + +## Response Format + +### Payment Required (402) + +``` +HTTP/1.1 402 Payment Required +Content-Type: application/json; charset=utf-8 +PAYMENT-REQUIRED: + +{} +``` + +The `PAYMENT-REQUIRED` header contains base64-encoded JSON with the payment requirements. Note: `amount` is in atomic units (e.g., 1000 = 0.001 USDC, since USDC has 6 decimals). + +```json +{ + "x402Version": 2, + "error": "Payment required", + "resource": { + "url": "http://localhost:4021/weather", + "description": "Weather data", + "mimeType": "application/json" + }, + "accepts": [ + { + "scheme": "exact", + "network": "eip155:84532", + "amount": "1000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "payTo": "0x...", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2", + "resourceUrl": "http://localhost:4021/weather" + } + } + ] +} +``` + +### Successful Response + +``` +HTTP/1.1 200 OK +Content-Type: application/json; charset=utf-8 +PAYMENT-RESPONSE: + +{"report":{"weather":"sunny","temperature":70}} +``` + +The `PAYMENT-RESPONSE` header contains base64-encoded JSON with the settlement details: + +```json +{ + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x...", + "requirements": { + "scheme": "exact", + "network": "eip155:84532", + "amount": "1000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "payTo": "0x...", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2", + "resourceUrl": "http://localhost:4021/weather" + } + } +} +``` diff --git a/examples/go/servers/advanced/bazaar.go b/examples/go/servers/advanced/bazaar.go new file mode 100644 index 000000000..4ae440435 --- /dev/null +++ b/examples/go/servers/advanced/bazaar.go @@ -0,0 +1,144 @@ +package main + +import ( + "fmt" + "net/http" + "os" + "time" + + x402 "github.com/coinbase/x402/go" + "github.com/coinbase/x402/go/extensions/bazaar" + "github.com/coinbase/x402/go/extensions/types" + x402http "github.com/coinbase/x402/go/http" + ginmw "github.com/coinbase/x402/go/http/gin" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + ginfw "github.com/gin-gonic/gin" + "github.com/joho/godotenv" +) + +const DefaultPort = "4021" + +/** + * Bazaar Discovery Extension Example + * + * This example demonstrates how to add the Bazaar discovery extension + * to make your x402-protected API discoverable by clients and facilitators. + * The extension includes input/output schemas and examples. + */ + +func main() { + godotenv.Load() + + evmPayeeAddress := os.Getenv("EVM_PAYEE_ADDRESS") + if evmPayeeAddress == "" { + fmt.Println("❌ EVM_PAYEE_ADDRESS environment variable is required") + os.Exit(1) + } + + facilitatorURL := os.Getenv("FACILITATOR_URL") + if facilitatorURL == "" { + fmt.Println("❌ FACILITATOR_URL environment variable is required") + os.Exit(1) + } + + evmNetwork := x402.Network("eip155:84532") // Base Sepolia + + r := ginfw.Default() + + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: facilitatorURL, + }) + + /** + * Create Bazaar Discovery Extension + * + * This extension provides machine-readable API documentation that allows + * clients to discover what parameters your API accepts and what it returns. + */ + discoveryExtension, err := bazaar.DeclareDiscoveryExtension( + bazaar.MethodGET, + map[string]interface{}{"city": "San Francisco"}, // Example query params + types.JSONSchema{ + "properties": map[string]interface{}{ + "city": map[string]interface{}{ + "type": "string", + "description": "City name to get weather for", + }, + }, + "required": []string{"city"}, + }, + "", // No body for GET request + &types.OutputConfig{ + Example: map[string]interface{}{ + "city": "San Francisco", + "weather": "foggy", + "temperature": 60, + }, + Schema: types.JSONSchema{ + "properties": map[string]interface{}{ + "city": map[string]interface{}{"type": "string"}, + "weather": map[string]interface{}{"type": "string"}, + "temperature": map[string]interface{}{"type": "number"}, + }, + "required": []string{"city", "weather", "temperature"}, + }, + }, + ) + if err != nil { + fmt.Printf("❌ Failed to create bazaar extension: %v\n", err) + os.Exit(1) + } + + routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.001", + Network: evmNetwork, + Description: "Get weather data for a city", + MimeType: "application/json", + Extensions: map[string]interface{}{ + types.BAZAAR: discoveryExtension, + }, + }, + } + + r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: evmNetwork, Server: evm.NewExactEvmScheme()}, + }, + Initialize: true, + Timeout: 30 * time.Second, + })) + + r.GET("/weather", func(c *ginfw.Context) { + city := c.DefaultQuery("city", "San Francisco") + + weatherData := map[string]map[string]interface{}{ + "San Francisco": {"weather": "foggy", "temperature": 60}, + "New York": {"weather": "cloudy", "temperature": 55}, + } + + data, exists := weatherData[city] + if !exists { + data = map[string]interface{}{"weather": "sunny", "temperature": 70} + } + + c.JSON(http.StatusOK, ginfw.H{ + "city": city, + "weather": data["weather"], + "temperature": data["temperature"], + }) + }) + + fmt.Printf("🚀 Bazaar Discovery example running on http://localhost:%s\n", DefaultPort) + fmt.Printf(" The /weather endpoint is discoverable via Bazaar\n") + + if err := r.Run(":" + DefaultPort); err != nil { + fmt.Printf("Error starting server: %v\n", err) + os.Exit(1) + } +} + diff --git a/examples/go/servers/advanced/custom-money-definition.go b/examples/go/servers/advanced/custom-money-definition.go new file mode 100644 index 000000000..0bb0e7ed1 --- /dev/null +++ b/examples/go/servers/advanced/custom-money-definition.go @@ -0,0 +1,127 @@ +package main + +import ( + "fmt" + "math" + "net/http" + "os" + "time" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + ginmw "github.com/coinbase/x402/go/http/gin" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + ginfw "github.com/gin-gonic/gin" + "github.com/joho/godotenv" +) + +const DefaultPort = "4021" + +/** + * Custom Money Definition Example + * + * This example demonstrates how to register custom money parsers to use + * alternative tokens or custom logic for converting prices to blockchain assets. + * This is useful when you want to accept payments in tokens other than the default USDC. + */ + +func main() { + godotenv.Load() + + evmPayeeAddress := os.Getenv("EVM_PAYEE_ADDRESS") + if evmPayeeAddress == "" { + fmt.Println("❌ EVM_PAYEE_ADDRESS environment variable is required") + os.Exit(1) + } + + facilitatorURL := os.Getenv("FACILITATOR_URL") + if facilitatorURL == "" { + fmt.Println("❌ FACILITATOR_URL environment variable is required") + os.Exit(1) + } + + evmNetwork := x402.Network("eip155:84532") // Base Sepolia + + r := ginfw.Default() + + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: facilitatorURL, + }) + + /** + * Create EVM Scheme with Custom Money Parser + * + * This demonstrates registering a custom money parser that handles + * specific network or amount conditions differently. + * + * For example, on Gnosis Chain (xDai) network, we could use Wrapped XDAI + * instead of USDC (this is for demonstration - WXDAI isn't EIP-3009 compliant). + */ + evmScheme := evm.NewExactEvmScheme().RegisterMoneyParser(func(amount float64, network x402.Network) (*x402.AssetAmount, error) { + // Custom logic for Gnosis Chain (eip155:100) + if string(network) == "eip155:100" { + return &x402.AssetAmount{ + Amount: fmt.Sprintf("%.0f", amount*1e18), // Wrapped XDAI has 18 decimals + Asset: "0xe91d153e0b41518a2ce8dd3d7944fa863463a97d", // WXDAI address on Gnosis + Extra: map[string]interface{}{ + "token": "Wrapped XDAI", + "network": "gnosis", + }, + }, nil + } + + // For large amounts on any network, use DAI instead of USDC + if amount > 100 { + return &x402.AssetAmount{ + Amount: fmt.Sprintf("%.0f", math.Round(amount*1e18)), // DAI has 18 decimals + Asset: "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb", // DAI on Base Sepolia + Extra: map[string]interface{}{ + "token": "DAI", + "tier": "large", + }, + }, nil + } + + // Return nil to use the default USDC parser for other cases + return nil, nil + }) + + routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.001", + Network: evmNetwork, + Description: "Weather data", + MimeType: "application/json", + }, + } + + r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: evmNetwork, Server: evmScheme}, // Use custom scheme + }, + Initialize: true, + Timeout: 30 * time.Second, + })) + + r.GET("/weather", func(c *ginfw.Context) { + c.JSON(http.StatusOK, ginfw.H{ + "report": ginfw.H{ + "weather": "sunny", + "temperature": 70, + }, + }) + }) + + fmt.Printf("🚀 Custom Money Definition example running on http://localhost:%s\n", DefaultPort) + fmt.Printf(" Using custom money parsers for different networks and amounts\n") + + if err := r.Run(":" + DefaultPort); err != nil { + fmt.Printf("Error starting server: %v\n", err) + os.Exit(1) + } +} + diff --git a/examples/go/servers/advanced/dynamic-pay-to.go b/examples/go/servers/advanced/dynamic-pay-to.go new file mode 100644 index 000000000..583521693 --- /dev/null +++ b/examples/go/servers/advanced/dynamic-pay-to.go @@ -0,0 +1,129 @@ +package main + +import ( + "context" + "fmt" + "net/http" + "os" + "time" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + ginmw "github.com/coinbase/x402/go/http/gin" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + ginfw "github.com/gin-gonic/gin" + "github.com/joho/godotenv" +) + +const DefaultPort = "4021" + +/** + * Dynamic PayTo Example + * + * This example demonstrates how to use dynamic payTo resolution to + * route payments to different addresses based on the request context. + * This is useful for marketplace applications where payments should + * go to different sellers/creators. + */ + +func main() { + godotenv.Load() + + evmPayeeAddress := os.Getenv("EVM_PAYEE_ADDRESS") + if evmPayeeAddress == "" { + fmt.Println("❌ EVM_PAYEE_ADDRESS environment variable is required") + os.Exit(1) + } + + facilitatorURL := os.Getenv("FACILITATOR_URL") + if facilitatorURL == "" { + fmt.Println("❌ FACILITATOR_URL environment variable is required") + os.Exit(1) + } + + evmNetwork := x402.Network("eip155:84532") // Base Sepolia + + r := ginfw.Default() + + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: facilitatorURL, + }) + + /** + * Address Lookup Table + * + * In a real application, you would query a database for the appropriate + * payee address. Here we use a simple lookup table for demonstration. + */ + addressLookup := map[string]string{ + "US": evmPayeeAddress, + "UK": evmPayeeAddress, + "CA": evmPayeeAddress, + "AU": evmPayeeAddress, + "NZ": evmPayeeAddress, + "IE": evmPayeeAddress, + "FR": evmPayeeAddress, + } + + /** + * Dynamic PayTo Function + * + * This function is called at request time to determine where the payment + * should be sent. It receives the full HTTP request context. + */ + dynamicPayTo := func(ctx context.Context, reqCtx x402http.HTTPRequestContext) (string, error) { + // Get the country from query parameter + country := "US" // default + if reqCtx.Adapter != nil { + // In a real implementation, you'd extract query params from the adapter + // For now, we'll use the default + } + + address, ok := addressLookup[country] + if !ok { + address = evmPayeeAddress // fallback to default + } + + fmt.Printf("💰 Routing payment for country=%s to address=%s\n", country, address) + return address, nil + } + + routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: x402http.DynamicPayToFunc(dynamicPayTo), + Price: "$0.001", + Network: evmNetwork, + Description: "Weather data", + MimeType: "application/json", + }, + } + + r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: evmNetwork, Server: evm.NewExactEvmScheme()}, + }, + Initialize: true, + Timeout: 30 * time.Second, + })) + + r.GET("/weather", func(c *ginfw.Context) { + c.JSON(http.StatusOK, ginfw.H{ + "report": ginfw.H{ + "weather": "sunny", + "temperature": 70, + }, + }) + }) + + fmt.Printf("🚀 Dynamic PayTo example running on http://localhost:%s\n", DefaultPort) + fmt.Printf(" Payments are routed based on request context\n") + + if err := r.Run(":" + DefaultPort); err != nil { + fmt.Printf("Error starting server: %v\n", err) + os.Exit(1) + } +} + diff --git a/examples/go/servers/advanced/dynamic-price.go b/examples/go/servers/advanced/dynamic-price.go new file mode 100644 index 000000000..ca87bd7be --- /dev/null +++ b/examples/go/servers/advanced/dynamic-price.go @@ -0,0 +1,140 @@ +package main + +import ( + "context" + "fmt" + "net/http" + "os" + "time" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + ginmw "github.com/coinbase/x402/go/http/gin" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + ginfw "github.com/gin-gonic/gin" + "github.com/joho/godotenv" +) + +const DefaultPort = "4021" + +/** + * Dynamic Price Example + * + * This example demonstrates how to use dynamic pricing to charge different + * amounts based on the request context. This is useful for implementing + * tiered pricing, user-based pricing, or content-based pricing. + */ + +func main() { + godotenv.Load() + + evmPayeeAddress := os.Getenv("EVM_PAYEE_ADDRESS") + if evmPayeeAddress == "" { + fmt.Println("❌ EVM_PAYEE_ADDRESS environment variable is required") + os.Exit(1) + } + + facilitatorURL := os.Getenv("FACILITATOR_URL") + if facilitatorURL == "" { + fmt.Println("❌ FACILITATOR_URL environment variable is required") + os.Exit(1) + } + + evmNetwork := x402.Network("eip155:84532") // Base Sepolia + + r := ginfw.Default() + + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: facilitatorURL, + }) + + /** + * Dynamic Price Function + * + * This function is called at request time to determine the price. + * It receives the full HTTP request context and can make decisions + * based on query parameters, headers, or any other request data. + */ + dynamicPrice := func(ctx context.Context, reqCtx x402http.HTTPRequestContext) (x402.Price, error) { + // In a real implementation, you would extract the tier from query params + // or headers using reqCtx.Adapter + + // For this example, we'll demonstrate the concept with a default tier + tier := "standard" // default + + // You could extract tier from request like: + // if reqCtx.Adapter != nil { + // tier = extractQueryParam(reqCtx.Adapter, "tier") + // } + + var price x402.Price + if tier == "premium" { + price = "$0.005" // Premium tier: 0.5 cents + fmt.Printf("💰 Premium tier pricing: %s\n", price) + } else { + price = "$0.001" // Standard tier: 0.1 cents + fmt.Printf("💰 Standard tier pricing: %s\n", price) + } + + return price, nil + } + + routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: x402http.DynamicPriceFunc(dynamicPrice), + Network: evmNetwork, + Description: "Weather data", + MimeType: "application/json", + }, + } + + r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: evmNetwork, Server: evm.NewExactEvmScheme()}, + }, + Initialize: true, + Timeout: 30 * time.Second, + })) + + r.GET("/weather", func(c *ginfw.Context) { + tier := c.DefaultQuery("tier", "standard") + + var response ginfw.H + if tier == "premium" { + // Premium tier gets detailed weather data + response = ginfw.H{ + "report": ginfw.H{ + "weather": "sunny", + "temperature": 70, + "humidity": 45, + "windSpeed": 12, + "precipitation": 0, + }, + } + } else { + // Standard tier gets basic weather data + response = ginfw.H{ + "report": ginfw.H{ + "weather": "sunny", + "temperature": 70, + }, + } + } + + c.JSON(http.StatusOK, response) + }) + + fmt.Printf("🚀 Dynamic Price example running on http://localhost:%s\n", DefaultPort) + fmt.Printf(" Prices vary based on request context\n") + fmt.Printf(" Try: ?tier=standard (cheaper) or ?tier=premium (more expensive)\n") + + if err := r.Run(":" + DefaultPort); err != nil { + fmt.Printf("Error starting server: %v\n", err) + os.Exit(1) + } +} + diff --git a/examples/go/servers/advanced/go.mod b/examples/go/servers/advanced/go.mod new file mode 100644 index 000000000..7fa7d6c77 --- /dev/null +++ b/examples/go/servers/advanced/go.mod @@ -0,0 +1,60 @@ +module github.com/coinbase/x402/examples/go/servers/advanced + +go 1.24.0 + +toolchain go1.24.1 + +replace github.com/coinbase/x402/go => ../../../../go + +require ( + github.com/coinbase/x402/go v0.0.0-00010101000000-000000000000 + github.com/gin-gonic/gin v1.11.0 + github.com/joho/godotenv v1.5.1 +) + +require ( + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.27.0 // indirect + github.com/goccy/go-json v0.10.4 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.55.0 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + golang.org/x/arch v0.20.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.36.0 // indirect + google.golang.org/protobuf v1.36.9 // indirect +) diff --git a/examples/go/servers/advanced/hooks.go b/examples/go/servers/advanced/hooks.go new file mode 100644 index 000000000..b847837fb --- /dev/null +++ b/examples/go/servers/advanced/hooks.go @@ -0,0 +1,90 @@ +package main + +import ( + "fmt" + "net/http" + "os" + "time" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + ginmw "github.com/coinbase/x402/go/http/gin" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + ginfw "github.com/gin-gonic/gin" + "github.com/joho/godotenv" +) + +const DefaultPort = "4021" + +/** + * Lifecycle Hooks Example + * + * This example demonstrates how to register hooks at different stages + * of the payment verification and settlement lifecycle. Hooks are useful + * for logging, custom validation, error recovery, and side effects. + */ + +func main() { + godotenv.Load() + + evmPayeeAddress := os.Getenv("EVM_PAYEE_ADDRESS") + if evmPayeeAddress == "" { + fmt.Println("❌ EVM_PAYEE_ADDRESS environment variable is required") + os.Exit(1) + } + + facilitatorURL := os.Getenv("FACILITATOR_URL") + if facilitatorURL == "" { + fmt.Println("❌ FACILITATOR_URL environment variable is required") + os.Exit(1) + } + + evmNetwork := x402.Network("eip155:84532") // Base Sepolia + + r := ginfw.Default() + + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: facilitatorURL, + }) + + evmScheme := evm.NewExactEvmScheme() + + routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.001", + Network: evmNetwork, + Description: "Weather data", + MimeType: "application/json", + }, + } + + r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: evmNetwork, Server: evmScheme}, + }, + Initialize: true, + Timeout: 30 * time.Second, + })) + + r.GET("/weather", func(c *ginfw.Context) { + c.JSON(http.StatusOK, ginfw.H{ + "report": ginfw.H{ + "weather": "sunny", + "temperature": 70, + }, + }) + }) + + fmt.Printf("🚀 Lifecycle Hooks example running on http://localhost:%s\n", DefaultPort) + fmt.Printf(" Watch the console for hook execution logs\n") + + if err := r.Run(":" + DefaultPort); err != nil { + fmt.Printf("Error starting server: %v\n", err) + os.Exit(1) + } +} + diff --git a/examples/go/servers/custom/.env-example b/examples/go/servers/custom/.env-example new file mode 100644 index 000000000..2693b3c42 --- /dev/null +++ b/examples/go/servers/custom/.env-example @@ -0,0 +1,2 @@ +EVM_PAYEE_ADDRESS= +FACILITATOR_URL= diff --git a/examples/go/servers/custom/.gitignore b/examples/go/servers/custom/.gitignore new file mode 100644 index 000000000..9e5f566b0 --- /dev/null +++ b/examples/go/servers/custom/.gitignore @@ -0,0 +1,25 @@ +# Environment variables +.env + +# Binaries +*.exe +*.exe~ +*.dll +*.so +*.dylib +main +server +custom + +# Go build artifacts +*.test +*.out +go.sum + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + diff --git a/examples/go/servers/custom/README.md b/examples/go/servers/custom/README.md new file mode 100644 index 000000000..513d3b64a --- /dev/null +++ b/examples/go/servers/custom/README.md @@ -0,0 +1,278 @@ +# x402-core Custom Server + +Gin server demonstrating how to implement x402 payment handling manually without using pre-built middleware packages like `x402/go/http/gin`. + +## Prerequisites + +- Go 1.24 or higher +- Valid EVM address for receiving payments +- URL of a facilitator supporting the desired payment network, see [facilitator list](https://www.x402.org/ecosystem?category=facilitators) + +## Setup + +1. Create a `.env` file with required environment variables: + +```bash +FACILITATOR_URL=https://x402.org/facilitator +EVM_PAYEE_ADDRESS=0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb +``` + +2. Install dependencies: + +```bash +go mod download +``` + +3. Run the server: + +```bash +go run main.go +``` + +## Testing the Server + +You can test the server using one of the example clients: + +### Using the Go HTTP Client + +```bash +cd ../../clients/http +# Ensure .env is setup +go run main.go +``` + +### Using the Custom Client + +```bash +cd ../../clients/custom +# Ensure .env is setup +go run main.go +``` + +These clients will demonstrate how to: + +1. Make an initial request to get payment requirements +2. Process the payment requirements +3. Make a second request with the payment token + +## Example Endpoint + +The server includes a single example endpoint at `/weather` that requires a payment of 0.001 USDC on Base Sepolia to access. The endpoint returns weather data for a given city. + +## HTTP Headers + +### Request Headers + +When submitting payment, include one of these headers (both are supported for backwards compatibility): + +| Header | Protocol | Description | +| ------------------- | -------- | ----------------------------------- | +| `PAYMENT-SIGNATURE` | v2 | Base64-encoded JSON payment payload | +| `X-PAYMENT` | v1 | Base64-encoded JSON payment payload | + +Example request with payment: + +``` +GET /weather HTTP/1.1 +Host: localhost:4021 +PAYMENT-SIGNATURE: eyJwYXltZW50IjoiLi4uIn0= +``` + +### Response Headers + +| Header | Status | Description | +| ------------------ | ------ | --------------------------------------------- | +| `PAYMENT-REQUIRED` | 402 | Base64-encoded JSON with payment requirements | +| `PAYMENT-RESPONSE` | 200 | Base64-encoded JSON with settlement details | + +## Response Format + +### Payment Required (402) + +``` +HTTP/1.1 402 Payment Required +Content-Type: application/json; charset=utf-8 +PAYMENT-REQUIRED: + +null +``` + +The `PAYMENT-REQUIRED` header contains base64-encoded JSON with the payment requirements: + +```json +{ + "x402Version": 2, + "error": "Payment required", + "resource": { + "url": "http://localhost:4021/weather", + "description": "Get weather data for a city", + "mimeType": "application/json" + }, + "accepts": [ + { + "scheme": "exact", + "network": "eip155:84532", + "amount": "1000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "payTo": "0x...", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2", + "resourceUrl": "http://localhost:4021/weather" + } + } + ] +} +``` + +### Successful Response (with payment) + +``` +HTTP/1.1 200 OK +Content-Type: application/json; charset=utf-8 +PAYMENT-RESPONSE: + +{"city":"San Francisco","weather":"foggy","temperature":60,"timestamp":"2024-01-01T12:00:00Z"} +``` + +The `PAYMENT-RESPONSE` header contains base64-encoded JSON with the settlement details: + +```json +{ + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x..." +} +``` + +## Payment Flow + +The custom implementation demonstrates each step of the x402 payment flow: + +1. **Request Arrives** — Middleware intercepts all requests +2. **Route Check** — Determine if route requires payment +3. **Payment Check** — Look for `PAYMENT-SIGNATURE` or `X-PAYMENT` header +4. **Decision Point**: + - **No Payment**: Return 402 with requirements in `PAYMENT-REQUIRED` header + - **Payment Provided**: Verify with facilitator +5. **Verification** — Check payment signature and validity +6. **Handler Execution** — Run protected endpoint handler +7. **Settlement** — Settle payment on-chain (for 2xx responses) +8. **Response** — Add settlement details in `PAYMENT-RESPONSE` header + +## Key Implementation Details + +### Defining Payment Requirements + +```go +routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.001", + Network: evmNetwork, + Description: "Get weather data for a city", + MimeType: "application/json", + }, +} +``` + +### Creating the x402 Server + +```go +x402Server := x402http.Newx402HTTPResourceServer( + routes, + x402.WithFacilitatorClient(facilitatorClient), + x402.WithSchemeServer(evmNetwork, evm.NewExactEvmScheme()), +) + +if err := x402Server.Initialize(ctx); err != nil { + fmt.Printf("Warning: failed to initialize x402 server: %v\n", err) +} +``` + +### Processing Requests + +```go +result := server.ProcessHTTPRequest(ctx, reqCtx, nil) + +switch result.Type { +case x402http.ResultNoPaymentRequired: + // No payment required, continue to handler + c.Next() + +case x402http.ResultPaymentError: + // Payment required but not provided or invalid + handlePaymentError(c, result.Response) + +case x402http.ResultPaymentVerified: + // Payment verified, continue with settlement handling + handlePaymentVerified(c, server, ctx, result) +} +``` + +### Settling Payment + +```go +settlementHeaders, err := server.ProcessSettlement( + ctx, + *result.PaymentPayload, + *result.PaymentRequirements, + capture.statusCode, +) + +if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Settlement failed", + "details": err.Error(), + }) + return +} + +// Add settlement headers to response +for key, value := range settlementHeaders { + c.Header(key, value) +} +``` + +## Middleware vs Custom Comparison + +| Aspect | With Middleware (ginmw) | Custom Implementation | +| ---------------------- | ----------------------- | --------------------- | +| Code Complexity | ~10 lines | ~400 lines | +| Automatic Verification | ✅ Yes | ❌ Manual | +| Automatic Settlement | ✅ Yes | ❌ Manual | +| Header Management | ✅ Automatic | ❌ Manual | +| Flexibility | Limited | ✅ Complete control | +| Error Handling | ✅ Built-in | ❌ You implement | +| Maintenance | x402 team | You maintain | + +## When to Use Each Approach + +**Use Middleware (x402/go/http/gin) when:** + +- Building standard applications +- Want quick integration +- Prefer automatic payment handling +- Using supported frameworks (Gin) + +**Use Custom Implementation when:** + +- Using unsupported frameworks (chi, Fiber, etc.) +- Need complete control over flow +- Require custom error handling +- Want to understand internals +- Building custom abstractions + +## Adapting to Other Frameworks + +To use this pattern with other frameworks: + +1. Implement the `x402http.HTTPAdapter` interface for your framework +2. Create a middleware function that uses `server.ProcessHTTPRequest()` +3. Handle the three result types: `NoPaymentRequired`, `PaymentError`, `PaymentVerified` +4. Use `server.ProcessSettlement()` to settle payments after successful responses + +The pattern in `main.go` can be adapted to any Go web framework. diff --git a/examples/go/servers/custom/go.mod b/examples/go/servers/custom/go.mod new file mode 100644 index 000000000..1896b9b7a --- /dev/null +++ b/examples/go/servers/custom/go.mod @@ -0,0 +1,57 @@ +module github.com/coinbase/x402/examples/go/servers/custom + +go 1.24.0 + +toolchain go1.24.1 + +replace github.com/coinbase/x402/go => ../../../../go + +require ( + github.com/coinbase/x402/go v0.0.0-00010101000000-000000000000 + github.com/gin-gonic/gin v1.11.0 + github.com/joho/godotenv v1.5.1 +) + +require ( + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.27.0 // indirect + github.com/goccy/go-json v0.10.4 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.55.0 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + golang.org/x/arch v0.20.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.36.0 // indirect + google.golang.org/protobuf v1.36.9 // indirect +) diff --git a/examples/go/servers/custom/main.go b/examples/go/servers/custom/main.go new file mode 100644 index 000000000..09ae4816f --- /dev/null +++ b/examples/go/servers/custom/main.go @@ -0,0 +1,405 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "os" + "sync" + "time" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + "github.com/gin-gonic/gin" + "github.com/joho/godotenv" +) + +const ( + DefaultPort = "4021" +) + +/** + * Custom Middleware Example - Direct x402 Integration + * + * This example demonstrates how to implement x402 payment handling WITHOUT + * using the pre-built middleware. It shows the implementation details of how + * to integrate x402 directly with any Go web framework. + * + * Use this example to: + * - Understand how x402 middleware works under the hood + * - Learn how to customize payment handling for your specific needs + * - See how to integrate x402 with custom web frameworks + */ + +// ============================================================================ +// Custom Gin Adapter +// ============================================================================ + +// CustomGinAdapter implements the HTTPAdapter interface for Gin +// This adapter translates Gin-specific HTTP operations to the x402 HTTP interface +type CustomGinAdapter struct { + ctx *gin.Context +} + +func NewCustomGinAdapter(ctx *gin.Context) *CustomGinAdapter { + return &CustomGinAdapter{ctx: ctx} +} + +func (a *CustomGinAdapter) GetHeader(name string) string { + return a.ctx.GetHeader(name) +} + +func (a *CustomGinAdapter) GetMethod() string { + return a.ctx.Request.Method +} + +func (a *CustomGinAdapter) GetPath() string { + return a.ctx.Request.URL.Path +} + +func (a *CustomGinAdapter) GetURL() string { + scheme := "http" + if a.ctx.Request.TLS != nil { + scheme = "https" + } + host := a.ctx.Request.Host + if host == "" { + host = a.ctx.GetHeader("Host") + } + return fmt.Sprintf("%s://%s%s", scheme, host, a.ctx.Request.URL.Path) +} + +func (a *CustomGinAdapter) GetAcceptHeader() string { + return a.ctx.GetHeader("Accept") +} + +func (a *CustomGinAdapter) GetUserAgent() string { + return a.ctx.GetHeader("User-Agent") +} + +// ============================================================================ +// Response Capture for Settlement +// ============================================================================ + +// ResponseCapture captures the response for settlement processing +// This allows us to inspect the response before sending it to the client +type ResponseCapture struct { + gin.ResponseWriter + body *bytes.Buffer + statusCode int + written bool + mu sync.Mutex +} + +func (w *ResponseCapture) WriteHeader(code int) { + w.mu.Lock() + defer w.mu.Unlock() + + if !w.written { + w.statusCode = code + w.written = true + } +} + +func (w *ResponseCapture) Write(data []byte) (int, error) { + w.mu.Lock() + defer w.mu.Unlock() + + if !w.written { + w.WriteHeader(http.StatusOK) + } + return w.body.Write(data) +} + +func (w *ResponseCapture) WriteString(s string) (int, error) { + return w.Write([]byte(s)) +} + +// ============================================================================ +// Custom Payment Middleware Implementation +// ============================================================================ + +// customPaymentMiddleware creates a custom x402 payment middleware +// This demonstrates the core logic of payment handling without using pre-built middleware +func customPaymentMiddleware(server *x402http.HTTPServer, timeout time.Duration) gin.HandlerFunc { + return func(c *gin.Context) { + // Create context with timeout for payment operations + ctx, cancel := context.WithTimeout(c.Request.Context(), timeout) + defer cancel() + + // Create adapter to translate Gin requests to x402 HTTP interface + adapter := NewCustomGinAdapter(c) + reqCtx := x402http.HTTPRequestContext{ + Adapter: adapter, + Path: c.Request.URL.Path, + Method: c.Request.Method, + } + + fmt.Printf("🔍 Processing request: %s %s\n", reqCtx.Method, reqCtx.Path) + + // Process the HTTP request through x402 + // This checks if payment is required, validates payment if provided, etc. + result := server.ProcessHTTPRequest(ctx, reqCtx, nil) + + // Handle different result types + switch result.Type { + case x402http.ResultNoPaymentRequired: + // No payment required for this route, continue to handler + fmt.Printf("✅ No payment required, continuing to handler\n") + c.Next() + + case x402http.ResultPaymentError: + // Payment is required but not provided or invalid + fmt.Printf("❌ Payment error: %d\n", result.Response.Status) + handlePaymentError(c, result.Response) + + case x402http.ResultPaymentVerified: + // Payment verified, continue with settlement handling + fmt.Printf("✅ Payment verified, proceeding to handler\n") + handlePaymentVerified(c, server, ctx, result) + } + } +} + +// handlePaymentError sends a payment required response to the client +func handlePaymentError(c *gin.Context, response *x402http.HTTPResponseInstructions) { + // Set status code + c.Status(response.Status) + + // Set headers (includes x402 payment requirements) + for key, value := range response.Headers { + c.Header(key, value) + } + + // Send response body + if response.IsHTML { + // HTML paywall for browsers + c.Data(response.Status, "text/html; charset=utf-8", []byte(response.Body.(string))) + } else { + // JSON response for API clients + c.JSON(response.Status, response.Body) + } + + // Abort to prevent further handlers from running + c.Abort() +} + +// handlePaymentVerified handles verified payments with settlement +func handlePaymentVerified(c *gin.Context, server *x402http.HTTPServer, ctx context.Context, result x402http.HTTPProcessResult) { + // Capture the response so we can inspect it before settlement + capture := &ResponseCapture{ + ResponseWriter: c.Writer, + body: &bytes.Buffer{}, + statusCode: http.StatusOK, + } + c.Writer = capture + + // Continue to the protected handler + c.Next() + + // Restore original writer + c.Writer = capture.ResponseWriter + + // Check if request was aborted by handler + if c.IsAborted() { + return + } + + // Don't settle if the handler returned an error + if capture.statusCode >= 400 { + fmt.Printf("⚠️ Handler returned error %d, skipping settlement\n", capture.statusCode) + c.Writer.WriteHeader(capture.statusCode) + c.Writer.Write(capture.body.Bytes()) + return + } + + fmt.Printf("💰 Settling payment...\n") + + // Process settlement through x402 + settlementHeaders, err := server.ProcessSettlement( + ctx, + *result.PaymentPayload, + *result.PaymentRequirements, + capture.statusCode, + ) + + if err != nil { + fmt.Printf("❌ Settlement failed: %v\n", err) + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Settlement failed", + "details": err.Error(), + }) + return + } + + fmt.Printf("✅ Settlement successful\n") + + // Add settlement headers to response + if settlementHeaders != nil { + for key, value := range settlementHeaders { + c.Header(key, value) + } + + // Log settlement details + if settlementHeaders["PAYMENT-RESPONSE"] != "" { + logSettlementDetails(settlementHeaders) + } + } + + // Write the captured response to the client + c.Writer.WriteHeader(capture.statusCode) + c.Writer.Write(capture.body.Bytes()) +} + +// logSettlementDetails extracts and logs settlement information +func logSettlementDetails(headers map[string]string) { + httpClient := x402http.Newx402HTTPClient(x402.Newx402Client()) + settleResponse, err := httpClient.GetPaymentSettleResponse(headers) + if err == nil { + fmt.Printf(" Transaction: %s\n", settleResponse.Transaction) + fmt.Printf(" Network: %s\n", settleResponse.Network) + fmt.Printf(" Payer: %s\n", settleResponse.Payer) + } +} + +// ============================================================================ +// Main Server +// ============================================================================ + +func main() { + // Load .env file if it exists + godotenv.Load() + + evmPayeeAddress := os.Getenv("EVM_PAYEE_ADDRESS") + if evmPayeeAddress == "" { + fmt.Println("❌ EVM_PAYEE_ADDRESS environment variable is required") + os.Exit(1) + } + + facilitatorURL := os.Getenv("FACILITATOR_URL") + if facilitatorURL == "" { + fmt.Println("❌ FACILITATOR_URL environment variable is required") + os.Exit(1) + } + + evmNetwork := x402.Network("eip155:84532") // Base Sepolia + + r := gin.Default() + + // ======================================================================== + // Configure x402 HTTP Server (Core Package) + // ======================================================================== + + // Create facilitator client for payment verification/settlement + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: facilitatorURL, + }) + + // Define routes and their payment requirements + routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.001", + Network: evmNetwork, + Description: "Get weather data for a city", + MimeType: "application/json", + }, + } + + // Create x402 HTTP server with core package + x402Server := x402http.Newx402HTTPResourceServer( + routes, + x402.WithFacilitatorClient(facilitatorClient), + x402.WithSchemeServer(evmNetwork, evm.NewExactEvmScheme()), + ) + + // Initialize the server (queries facilitator for supported schemes) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + if err := x402Server.Initialize(ctx); err != nil { + fmt.Printf("⚠️ Warning: failed to initialize x402 server: %v\n", err) + } + + // ======================================================================== + // Apply Custom Payment Middleware + // ======================================================================== + + // Use our custom middleware implementation + r.Use(customPaymentMiddleware(x402Server, 30*time.Second)) + + // ======================================================================== + // Protected Route Handler + // ======================================================================== + + r.GET("/weather", func(c *gin.Context) { + city := c.DefaultQuery("city", "San Francisco") + + weatherData := map[string]map[string]interface{}{ + "San Francisco": {"weather": "foggy", "temperature": 60}, + "New York": {"weather": "cloudy", "temperature": 55}, + "London": {"weather": "rainy", "temperature": 50}, + "Tokyo": {"weather": "clear", "temperature": 65}, + } + + data, exists := weatherData[city] + if !exists { + data = map[string]interface{}{"weather": "sunny", "temperature": 70} + } + + c.JSON(http.StatusOK, gin.H{ + "city": city, + "weather": data["weather"], + "temperature": data["temperature"], + "timestamp": time.Now().Format(time.RFC3339), + }) + }) + + // ======================================================================== + // Public Routes (No Payment Required) + // ======================================================================== + + r.GET("/health", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "status": "ok", + "version": "2.0.0", + }) + }) + + // Debug endpoint to inspect payment requirements + r.GET("/debug/requirements", func(c *gin.Context) { + ctx := context.Background() + requirements, err := x402Server.BuildPaymentRequirementsFromConfig(ctx, x402.ResourceConfig{ + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.001", + Network: evmNetwork, + }) + + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + // Pretty print requirements + pretty, _ := json.MarshalIndent(requirements, "", " ") + c.Data(http.StatusOK, "application/json", pretty) + }) + + // ======================================================================== + // Start Server + // ======================================================================== + + fmt.Printf("🚀 Server: %s on %s\n", evmPayeeAddress, evmNetwork) + fmt.Printf(" Listening on http://localhost:%s\n\n", DefaultPort) + + if err := r.Run(":" + DefaultPort); err != nil { + fmt.Printf("Error starting server: %v\n", err) + os.Exit(1) + } +} + diff --git a/examples/go/servers/gin/.env-example b/examples/go/servers/gin/.env-example new file mode 100644 index 000000000..2693b3c42 --- /dev/null +++ b/examples/go/servers/gin/.env-example @@ -0,0 +1,2 @@ +EVM_PAYEE_ADDRESS= +FACILITATOR_URL= diff --git a/examples/go/servers/gin/.gitignore b/examples/go/servers/gin/.gitignore new file mode 100644 index 000000000..8acdd4dc0 --- /dev/null +++ b/examples/go/servers/gin/.gitignore @@ -0,0 +1,24 @@ +# Environment variables +.env + +# Binaries +*.exe +*.exe~ +*.dll +*.so +*.dylib +gin +server + +# Go build artifacts +*.test +*.out +go.sum + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + diff --git a/examples/go/servers/gin/README.md b/examples/go/servers/gin/README.md new file mode 100644 index 000000000..1458aa07a --- /dev/null +++ b/examples/go/servers/gin/README.md @@ -0,0 +1,204 @@ +# x402-gin Example Server + +Gin server demonstrating how to protect API endpoints with a paywall using the +`x402/go/http/gin` middleware. + +## Prerequisites + +- Go 1.24 or higher +- Valid EVM address for receiving payments +- URL of a facilitator supporting the desired payment network, see [facilitator list](https://www.x402.org/ecosystem?category=facilitators) + +## Setup + +1. Copy `.env-example` to `.env`: + +```bash +cp .env-example .env +``` + +and fill required environment variables: + +- `FACILITATOR_URL` - Facilitator endpoint URL +- `EVM_PAYEE_ADDRESS` - Ethereum address to receive payments + +2. Install dependencies: +```bash +go mod download +``` + +3. Run the server: +```bash +go run main.go +``` + +## Testing the Server + +You can test the server using one of the example clients: + +### Using the Go HTTP Client +```bash +cd ../../clients/http +# Ensure .env is setup +go run main.go +``` + +These clients will demonstrate how to: +1. Make an initial request to get payment requirements +2. Process the payment requirements +3. Make a second request with the payment token + +## Example Endpoint + +The server includes a single example endpoint at `/weather` that requires a payment of 0.001 USDC on Base Sepolia to access. The endpoint returns a simple weather report. + +## Response Format + +### Payment Required (402) + +``` +HTTP/1.1 402 Payment Required +Content-Type: application/json; charset=utf-8 +PAYMENT-REQUIRED: + +null +``` + +The `PAYMENT-REQUIRED` header contains base64-encoded JSON with the payment requirements. +Note: `amount` is in atomic units (e.g., 1000 = 0.001 USDC, since USDC has 6 decimals): + +```json +{ + "x402Version": 2, + "error": "Payment required", + "resource": { + "url": "http://localhost:4021/weather", + "description": "Get weather data for a city", + "mimeType": "application/json" + }, + "accepts": [ + { + "scheme": "exact", + "network": "eip155:84532", + "amount": "1000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "payTo": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2", + "resourceUrl": "http://localhost:4021/weather" + } + } + ] +} +``` + +### Successful Response + +``` +HTTP/1.1 200 OK +Content-Type: application/json; charset=utf-8 +PAYMENT-RESPONSE: + +{"city":"San Francisco","weather":"foggy","temperature":60,"timestamp":"2025-01-01T12:00:00Z"} +``` + +The `PAYMENT-RESPONSE` header contains base64-encoded JSON with the settlement details: + +```json +{ + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x..." +} +``` + +## Extending the Example + +To add more paid endpoints, follow this pattern: + +```go +// First, configure the payment middleware with your routes +routes := x402http.RoutesConfig{ + "GET /your-endpoint": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.10", + Network: x402.Network("eip155:84532"), + Description: "Your endpoint description", + MimeType: "application/json", + }, +} + +r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: x402.Network("eip155:*"), Server: evm.NewExactEvmScheme()}, + }, + Initialize: true, +})) + +// Then define your routes as normal +r.GET("/your-endpoint", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + // Your response data + }) +}) +``` + +**Network identifiers** use [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) format, for example: +- `eip155:84532` — Base Sepolia +- `eip155:8453` — Base Mainnet +- `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` — Solana Devnet +- `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` — Solana Mainnet + +## x402ResourceServer Config + +The middleware uses scheme registrations to declare how payments for each network should be processed: + +```go +r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: x402.Network("eip155:*"), Server: evm.NewExactEvmScheme()}, // All EVM chains + // {Network: x402.Network("solana:*"), Server: svm.NewExactSvmScheme()}, // All SVM chains + }, + Initialize: true, + Timeout: 30 * time.Second, +})) +``` + +## Facilitator Config + +The `HTTPFacilitatorClient` connects to a facilitator service that verifies and settles payments on-chain: + +```go +facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: facilitatorURL, +}) + +// Or use multiple facilitators for redundancy +facilitatorClients := []x402.FacilitatorClient{ + x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{URL: primaryFacilitatorURL}), + x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{URL: backupFacilitatorURL}), +} +``` + +## Next Steps + +See [Advanced Examples](../advanced/) for: +- **Bazaar discovery** — make your API discoverable +- **Dynamic pricing** — price based on request context +- **Dynamic payTo** — route payments to different recipients +- **Lifecycle hooks** — custom logic on verify/settle +- **Custom tokens** — accept payments in custom tokens + +## Related Resources + +- [Gin Documentation](https://gin-gonic.com/docs/) +- [x402 Go Package Documentation](../../../../go/) +- [Client Examples](../../clients/) — build clients that can make paid requests diff --git a/examples/go/servers/gin/go.mod b/examples/go/servers/gin/go.mod new file mode 100644 index 000000000..b9b59e157 --- /dev/null +++ b/examples/go/servers/gin/go.mod @@ -0,0 +1,60 @@ +module github.com/coinbase/x402/examples/go/servers/gin + +go 1.24.0 + +toolchain go1.24.1 + +replace github.com/coinbase/x402/go => ../../../../go + +require ( + github.com/coinbase/x402/go v0.0.0-00010101000000-000000000000 + github.com/gin-gonic/gin v1.11.0 + github.com/joho/godotenv v1.5.1 +) + +require ( + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-ethereum v1.16.7 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.27.0 // indirect + github.com/goccy/go-json v0.10.4 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect + github.com/holiman/uint256 v1.3.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.55.0 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + golang.org/x/arch v0.20.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.36.0 // indirect + google.golang.org/protobuf v1.36.9 // indirect +) diff --git a/examples/go/servers/gin/main.go b/examples/go/servers/gin/main.go new file mode 100644 index 000000000..7ccf9a3b3 --- /dev/null +++ b/examples/go/servers/gin/main.go @@ -0,0 +1,132 @@ +package main + +import ( + "fmt" + "net/http" + "os" + "time" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + ginmw "github.com/coinbase/x402/go/http/gin" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + ginfw "github.com/gin-gonic/gin" + "github.com/joho/godotenv" +) + +const ( + DefaultPort = "4021" +) + +func main() { + godotenv.Load() + + evmPayeeAddress := os.Getenv("EVM_PAYEE_ADDRESS") + if evmPayeeAddress == "" { + fmt.Println("❌ EVM_PAYEE_ADDRESS environment variable is required") + fmt.Println(" Set your Ethereum address to receive payments") + os.Exit(1) + } + + facilitatorURL := os.Getenv("FACILITATOR_URL") + if facilitatorURL == "" { + fmt.Println("❌ FACILITATOR_URL environment variable is required") + fmt.Println(" Example: https://x402.org/facilitator") + os.Exit(1) + } + + // Network configuration - Base Sepolia testnet + evmNetwork := x402.Network("eip155:84532") + + fmt.Printf("🚀 Starting Gin x402 server...\n") + fmt.Printf(" Payee address: %s\n", evmPayeeAddress) + fmt.Printf(" Facilitator: %s\n", facilitatorURL) + fmt.Printf(" Network: %s\n", evmNetwork) + + // Create Gin router + r := ginfw.Default() + + // Create HTTP facilitator client + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: facilitatorURL, + }) + + /** + * Configure x402 payment middleware + * + * This middleware protects specific routes with payment requirements. + * When a client accesses a protected route without payment, they receive + * a 402 Payment Required response with payment details. + */ + routes := x402http.RoutesConfig{ + "GET /weather": { + Scheme: "exact", + PayTo: evmPayeeAddress, + Price: "$0.001", // 0.1 cents in USDC + Network: evmNetwork, + Description: "Get weather data for a city", + MimeType: "application/json", + }, + } + + // Apply x402 payment middleware + r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: evmNetwork, Server: evm.NewExactEvmScheme()}, + }, + Initialize: true, + Timeout: 30 * time.Second, + })) + + /** + * Protected endpoint - requires $0.001 USDC payment + * + * Clients must provide a valid x402 payment to access this endpoint. + * The payment is verified and settled before the endpoint handler runs. + */ + r.GET("/weather", func(c *ginfw.Context) { + city := c.DefaultQuery("city", "San Francisco") + + weatherData := map[string]map[string]interface{}{ + "San Francisco": {"weather": "foggy", "temperature": 60}, + "New York": {"weather": "cloudy", "temperature": 55}, + "London": {"weather": "rainy", "temperature": 50}, + "Tokyo": {"weather": "clear", "temperature": 65}, + } + + data, exists := weatherData[city] + if !exists { + data = map[string]interface{}{"weather": "sunny", "temperature": 70} + } + + c.JSON(http.StatusOK, ginfw.H{ + "city": city, + "weather": data["weather"], + "temperature": data["temperature"], + "timestamp": time.Now().Format(time.RFC3339), + }) + }) + + /** + * Health check endpoint - no payment required + * + * This endpoint is not protected by x402 middleware. + */ + r.GET("/health", func(c *ginfw.Context) { + c.JSON(http.StatusOK, ginfw.H{ + "status": "ok", + "version": "2.0.0", + }) + }) + + fmt.Printf("🚀 Server: %s on %s\n", evmPayeeAddress, evmNetwork) + fmt.Printf(" Listening on http://localhost:%s\n\n", DefaultPort) + + if err := r.Run(":" + DefaultPort); err != nil { + fmt.Printf("Error starting server: %v\n", err) + os.Exit(1) + } +} + diff --git a/examples/python/README.md b/examples/python/legacy/README.md similarity index 100% rename from examples/python/README.md rename to examples/python/legacy/README.md diff --git a/examples/python/clients/httpx/.env-local b/examples/python/legacy/clients/httpx/.env-local similarity index 100% rename from examples/python/clients/httpx/.env-local rename to examples/python/legacy/clients/httpx/.env-local diff --git a/examples/python/clients/httpx/README.md b/examples/python/legacy/clients/httpx/README.md similarity index 100% rename from examples/python/clients/httpx/README.md rename to examples/python/legacy/clients/httpx/README.md diff --git a/examples/python/clients/httpx/extensible.py b/examples/python/legacy/clients/httpx/extensible.py similarity index 100% rename from examples/python/clients/httpx/extensible.py rename to examples/python/legacy/clients/httpx/extensible.py diff --git a/examples/python/clients/httpx/main.py b/examples/python/legacy/clients/httpx/main.py similarity index 100% rename from examples/python/clients/httpx/main.py rename to examples/python/legacy/clients/httpx/main.py diff --git a/examples/python/clients/httpx/pyproject.toml b/examples/python/legacy/clients/httpx/pyproject.toml similarity index 100% rename from examples/python/clients/httpx/pyproject.toml rename to examples/python/legacy/clients/httpx/pyproject.toml diff --git a/examples/python/clients/httpx/uv.lock b/examples/python/legacy/clients/httpx/uv.lock similarity index 100% rename from examples/python/clients/httpx/uv.lock rename to examples/python/legacy/clients/httpx/uv.lock diff --git a/examples/python/clients/requests/.env-local b/examples/python/legacy/clients/requests/.env-local similarity index 100% rename from examples/python/clients/requests/.env-local rename to examples/python/legacy/clients/requests/.env-local diff --git a/examples/python/clients/requests/README.md b/examples/python/legacy/clients/requests/README.md similarity index 100% rename from examples/python/clients/requests/README.md rename to examples/python/legacy/clients/requests/README.md diff --git a/examples/python/clients/requests/extensible.py b/examples/python/legacy/clients/requests/extensible.py similarity index 100% rename from examples/python/clients/requests/extensible.py rename to examples/python/legacy/clients/requests/extensible.py diff --git a/examples/python/clients/requests/main.py b/examples/python/legacy/clients/requests/main.py similarity index 100% rename from examples/python/clients/requests/main.py rename to examples/python/legacy/clients/requests/main.py diff --git a/examples/python/clients/requests/pyproject.toml b/examples/python/legacy/clients/requests/pyproject.toml similarity index 100% rename from examples/python/clients/requests/pyproject.toml rename to examples/python/legacy/clients/requests/pyproject.toml diff --git a/examples/python/clients/requests/uv.lock b/examples/python/legacy/clients/requests/uv.lock similarity index 100% rename from examples/python/clients/requests/uv.lock rename to examples/python/legacy/clients/requests/uv.lock diff --git a/examples/python/discovery/README.md b/examples/python/legacy/discovery/README.md similarity index 100% rename from examples/python/discovery/README.md rename to examples/python/legacy/discovery/README.md diff --git a/examples/python/discovery/main.py b/examples/python/legacy/discovery/main.py similarity index 100% rename from examples/python/discovery/main.py rename to examples/python/legacy/discovery/main.py diff --git a/examples/python/discovery/pyproject.toml b/examples/python/legacy/discovery/pyproject.toml similarity index 100% rename from examples/python/discovery/pyproject.toml rename to examples/python/legacy/discovery/pyproject.toml diff --git a/examples/python/discovery/uv.lock b/examples/python/legacy/discovery/uv.lock similarity index 100% rename from examples/python/discovery/uv.lock rename to examples/python/legacy/discovery/uv.lock diff --git a/examples/python/fullstack/fastapi/.env-local b/examples/python/legacy/fullstack/fastapi/.env-local similarity index 100% rename from examples/python/fullstack/fastapi/.env-local rename to examples/python/legacy/fullstack/fastapi/.env-local diff --git a/examples/python/fullstack/fastapi/README.md b/examples/python/legacy/fullstack/fastapi/README.md similarity index 100% rename from examples/python/fullstack/fastapi/README.md rename to examples/python/legacy/fullstack/fastapi/README.md diff --git a/examples/python/fullstack/fastapi/main.py b/examples/python/legacy/fullstack/fastapi/main.py similarity index 100% rename from examples/python/fullstack/fastapi/main.py rename to examples/python/legacy/fullstack/fastapi/main.py diff --git a/examples/python/fullstack/fastapi/pyproject.toml b/examples/python/legacy/fullstack/fastapi/pyproject.toml similarity index 100% rename from examples/python/fullstack/fastapi/pyproject.toml rename to examples/python/legacy/fullstack/fastapi/pyproject.toml diff --git a/examples/python/fullstack/fastapi/static/premium.html b/examples/python/legacy/fullstack/fastapi/static/premium.html similarity index 100% rename from examples/python/fullstack/fastapi/static/premium.html rename to examples/python/legacy/fullstack/fastapi/static/premium.html diff --git a/examples/python/fullstack/fastapi/static/x402.png b/examples/python/legacy/fullstack/fastapi/static/x402.png similarity index 100% rename from examples/python/fullstack/fastapi/static/x402.png rename to examples/python/legacy/fullstack/fastapi/static/x402.png diff --git a/examples/python/fullstack/fastapi/uv.lock b/examples/python/legacy/fullstack/fastapi/uv.lock similarity index 100% rename from examples/python/fullstack/fastapi/uv.lock rename to examples/python/legacy/fullstack/fastapi/uv.lock diff --git a/examples/python/fullstack/flask/.env-local b/examples/python/legacy/fullstack/flask/.env-local similarity index 100% rename from examples/python/fullstack/flask/.env-local rename to examples/python/legacy/fullstack/flask/.env-local diff --git a/examples/python/fullstack/flask/README.md b/examples/python/legacy/fullstack/flask/README.md similarity index 100% rename from examples/python/fullstack/flask/README.md rename to examples/python/legacy/fullstack/flask/README.md diff --git a/examples/python/fullstack/flask/main.py b/examples/python/legacy/fullstack/flask/main.py similarity index 100% rename from examples/python/fullstack/flask/main.py rename to examples/python/legacy/fullstack/flask/main.py diff --git a/examples/python/fullstack/flask/pyproject.toml b/examples/python/legacy/fullstack/flask/pyproject.toml similarity index 100% rename from examples/python/fullstack/flask/pyproject.toml rename to examples/python/legacy/fullstack/flask/pyproject.toml diff --git a/examples/python/fullstack/flask/static/premium.html b/examples/python/legacy/fullstack/flask/static/premium.html similarity index 100% rename from examples/python/fullstack/flask/static/premium.html rename to examples/python/legacy/fullstack/flask/static/premium.html diff --git a/examples/python/fullstack/flask/static/x402.png b/examples/python/legacy/fullstack/flask/static/x402.png similarity index 100% rename from examples/python/fullstack/flask/static/x402.png rename to examples/python/legacy/fullstack/flask/static/x402.png diff --git a/examples/python/fullstack/flask/uv.lock b/examples/python/legacy/fullstack/flask/uv.lock similarity index 100% rename from examples/python/fullstack/flask/uv.lock rename to examples/python/legacy/fullstack/flask/uv.lock diff --git a/examples/python/servers/advanced/.env-local b/examples/python/legacy/servers/advanced/.env-local similarity index 100% rename from examples/python/servers/advanced/.env-local rename to examples/python/legacy/servers/advanced/.env-local diff --git a/examples/python/servers/advanced/README.md b/examples/python/legacy/servers/advanced/README.md similarity index 100% rename from examples/python/servers/advanced/README.md rename to examples/python/legacy/servers/advanced/README.md diff --git a/examples/python/servers/advanced/main.py b/examples/python/legacy/servers/advanced/main.py similarity index 100% rename from examples/python/servers/advanced/main.py rename to examples/python/legacy/servers/advanced/main.py diff --git a/examples/python/servers/advanced/pyproject.toml b/examples/python/legacy/servers/advanced/pyproject.toml similarity index 100% rename from examples/python/servers/advanced/pyproject.toml rename to examples/python/legacy/servers/advanced/pyproject.toml diff --git a/examples/python/servers/advanced/uv.lock b/examples/python/legacy/servers/advanced/uv.lock similarity index 100% rename from examples/python/servers/advanced/uv.lock rename to examples/python/legacy/servers/advanced/uv.lock diff --git a/examples/python/servers/fastapi/.env-local b/examples/python/legacy/servers/fastapi/.env-local similarity index 100% rename from examples/python/servers/fastapi/.env-local rename to examples/python/legacy/servers/fastapi/.env-local diff --git a/examples/python/servers/fastapi/README.md b/examples/python/legacy/servers/fastapi/README.md similarity index 100% rename from examples/python/servers/fastapi/README.md rename to examples/python/legacy/servers/fastapi/README.md diff --git a/examples/python/servers/fastapi/main.py b/examples/python/legacy/servers/fastapi/main.py similarity index 100% rename from examples/python/servers/fastapi/main.py rename to examples/python/legacy/servers/fastapi/main.py diff --git a/examples/python/servers/fastapi/pyproject.toml b/examples/python/legacy/servers/fastapi/pyproject.toml similarity index 100% rename from examples/python/servers/fastapi/pyproject.toml rename to examples/python/legacy/servers/fastapi/pyproject.toml diff --git a/examples/python/servers/fastapi/uv.lock b/examples/python/legacy/servers/fastapi/uv.lock similarity index 100% rename from examples/python/servers/fastapi/uv.lock rename to examples/python/legacy/servers/fastapi/uv.lock diff --git a/examples/python/servers/flask/.env-local b/examples/python/legacy/servers/flask/.env-local similarity index 100% rename from examples/python/servers/flask/.env-local rename to examples/python/legacy/servers/flask/.env-local diff --git a/examples/python/servers/flask/README.md b/examples/python/legacy/servers/flask/README.md similarity index 100% rename from examples/python/servers/flask/README.md rename to examples/python/legacy/servers/flask/README.md diff --git a/examples/python/servers/flask/main.py b/examples/python/legacy/servers/flask/main.py similarity index 100% rename from examples/python/servers/flask/main.py rename to examples/python/legacy/servers/flask/main.py diff --git a/examples/python/servers/flask/pyproject.toml b/examples/python/legacy/servers/flask/pyproject.toml similarity index 100% rename from examples/python/servers/flask/pyproject.toml rename to examples/python/legacy/servers/flask/pyproject.toml diff --git a/examples/python/servers/flask/uv.lock b/examples/python/legacy/servers/flask/uv.lock similarity index 100% rename from examples/python/servers/flask/uv.lock rename to examples/python/legacy/servers/flask/uv.lock diff --git a/examples/python/servers/mainnet/.env-local b/examples/python/legacy/servers/mainnet/.env-local similarity index 100% rename from examples/python/servers/mainnet/.env-local rename to examples/python/legacy/servers/mainnet/.env-local diff --git a/examples/python/servers/mainnet/README.md b/examples/python/legacy/servers/mainnet/README.md similarity index 100% rename from examples/python/servers/mainnet/README.md rename to examples/python/legacy/servers/mainnet/README.md diff --git a/examples/python/servers/mainnet/main.py b/examples/python/legacy/servers/mainnet/main.py similarity index 100% rename from examples/python/servers/mainnet/main.py rename to examples/python/legacy/servers/mainnet/main.py diff --git a/examples/python/servers/mainnet/pyproject.toml b/examples/python/legacy/servers/mainnet/pyproject.toml similarity index 100% rename from examples/python/servers/mainnet/pyproject.toml rename to examples/python/legacy/servers/mainnet/pyproject.toml diff --git a/examples/python/servers/mainnet/uv.lock b/examples/python/legacy/servers/mainnet/uv.lock similarity index 100% rename from examples/python/servers/mainnet/uv.lock rename to examples/python/legacy/servers/mainnet/uv.lock diff --git a/examples/python/sync.py b/examples/python/legacy/sync.py similarity index 100% rename from examples/python/sync.py rename to examples/python/legacy/sync.py diff --git a/examples/typescript/clients/advanced/.env-local b/examples/typescript/clients/advanced/.env-local new file mode 100644 index 000000000..8339ac0ab --- /dev/null +++ b/examples/typescript/clients/advanced/.env-local @@ -0,0 +1,4 @@ +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= +RESOURCE_SERVER_URL=http://localhost:4021 +ENDPOINT_PATH=/weather \ No newline at end of file diff --git a/examples/typescript/mcp-embedded-wallet/.prettierrc b/examples/typescript/clients/advanced/.prettierrc similarity index 100% rename from examples/typescript/mcp-embedded-wallet/.prettierrc rename to examples/typescript/clients/advanced/.prettierrc diff --git a/examples/typescript/clients/advanced/README.md b/examples/typescript/clients/advanced/README.md new file mode 100644 index 000000000..df7af4a74 --- /dev/null +++ b/examples/typescript/clients/advanced/README.md @@ -0,0 +1,151 @@ +# Advanced x402 Client Examples + +Advanced patterns for x402 TypeScript clients demonstrating payment lifecycle hooks and network preferences. + +## Prerequisites + +- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) +- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) +- Valid EVM and/or SVM private keys for making payments +- A running x402 server (see [server examples](../../servers/)) +- Familiarity with the [basic fetch client](../fetch/) + +## Setup + +1. Copy `.env-local` to `.env`: + +```bash +cp .env-local .env +``` + +and fill required environment variables: + +- `EVM_PRIVATE_KEY` - Ethereum private key for EVM payments +- `SVM_PRIVATE_KEY` - Solana private key for SVM payments (required for preferred-network) + +2. Install and build all packages from the typescript examples root: + +```bash +cd ../../ +pnpm install && pnpm build +cd clients/advanced +``` + +3. Run the server + +```bash +pnpm dev +``` + +## Available Examples + +Each example demonstrates a specific advanced pattern: + +| Example | Command | Description | +| ------------------- | ---------------------------- | ------------------------------- | +| `hooks` | `pnpm dev:hooks` | Payment lifecycle hooks | +| `preferred-network` | `pnpm dev:preferred-network` | Client-side network preferences | + +## Testing the Examples + +Start a server first: + +```bash +cd ../../servers/express +pnpm dev +``` + +Then run the examples: + +```bash +cd ../../clients/advanced +pnpm dev:hooks +``` + +## Example: Payment Lifecycle Hooks + +Register custom logic at different payment stages for observability and control: + +```typescript +import { x402Client, wrapFetchWithPayment } from "@x402/fetch"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { privateKeyToAccount } from "viem/accounts"; + +const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY); + +const client = new x402Client() + .register("eip155:*", new ExactEvmScheme(signer)) + .onBeforePaymentCreation(async context => { + console.log("Creating payment for:", context.selectedRequirements); + // Abort payment by returning: { abort: true, reason: "Not allowed" } + }) + .onAfterPaymentCreation(async context => { + console.log("Payment created:", context.paymentPayload.x402Version); + // Send to analytics, database, etc. + }) + .onPaymentCreationFailure(async context => { + console.error("Payment failed:", context.error); + // Recover by returning: { recovered: true, payload: alternativePayload } + }); + +const fetchWithPayment = wrapFetchWithPayment(fetch, client); +const response = await fetchWithPayment("http://localhost:4021/weather"); +``` + +Available hooks: + +- `onBeforePaymentCreation` — Run before payment creation (can abort) +- `onAfterPaymentCreation` — Run after successful payment creation +- `onPaymentCreationFailure` — Run when payment creation fails (can recover) + +**Use case:** + +- Log payment events for debugging and monitoring +- Custom validation before allowing payments +- Implement retry or recovery logic for failed payments +- Metrics and analytics collection + +## Example: Preferred Network Selection + +Configure client-side network preferences with automatic fallback: + +```typescript +import { x402Client, wrapFetchWithPayment, type PaymentRequirements } from "@x402/fetch"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { ExactSvmScheme } from "@x402/svm/exact/client"; + +// Define network preference order (most preferred first) +const networkPreferences = ["solana:", "eip155:"]; + +const preferredNetworkSelector = ( + _x402Version: number, + options: PaymentRequirements[], +): PaymentRequirements => { + // Try each preference in order + for (const preference of networkPreferences) { + const match = options.find(opt => opt.network.startsWith(preference)); + if (match) return match; + } + // Fallback to first mutually-supported option + return options[0]; +}; + +const client = new x402Client(preferredNetworkSelector) + .register("eip155:*", new ExactEvmScheme(evmSigner)) + .register("solana:*", new ExactSvmScheme(svmSigner)); + +const fetchWithPayment = wrapFetchWithPayment(fetch, client); +const response = await fetchWithPayment("http://localhost:4021/weather"); +``` + +**Use case:** + +- Prefer payments on specific chains +- User preference settings in wallet UIs + +## Hook Best Practices + +1. **Keep hooks fast** — Avoid blocking operations +2. **Handle errors gracefully** — Don't throw in hooks +3. **Log appropriately** — Use structured logging +4. **Avoid side effects in before hooks** — Only use for validation diff --git a/examples/typescript/discovery/eslint.config.js b/examples/typescript/clients/advanced/eslint.config.js similarity index 100% rename from examples/typescript/discovery/eslint.config.js rename to examples/typescript/clients/advanced/eslint.config.js diff --git a/examples/typescript/clients/advanced/hooks.ts b/examples/typescript/clients/advanced/hooks.ts new file mode 100644 index 000000000..79e419f8b --- /dev/null +++ b/examples/typescript/clients/advanced/hooks.ts @@ -0,0 +1,73 @@ +import { privateKeyToAccount } from "viem/accounts"; +import { x402Client } from "@x402/fetch"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; + +/** + * Hooks Example + * + * This demonstrates how to register hooks for payment creation lifecycle events. + * Hooks allow you to add custom logic at different stages: + * - onBeforePaymentCreation: Called before payment creation starts, can abort + * - onAfterPaymentCreation: Called after successful payment creation + * - onPaymentCreationFailure: Called when payment creation fails, can recover + * + * This is an advanced feature useful for: + * - Logging payment events for debugging and monitoring + * - Custom validation before allowing payments + * - Error recovery strategies + * - Metrics and analytics collection + * + * @param evmPrivateKey - The EVM private key for signing + * @param url - The URL to make the request to + */ +export async function runHooksExample(evmPrivateKey: `0x${string}`, url: string): Promise { + console.log("🔧 Creating client with payment lifecycle hooks...\n"); + + const evmSigner = privateKeyToAccount(evmPrivateKey); + + const client = new x402Client() + .register("eip155:*", new ExactEvmScheme(evmSigner)) + .onBeforePaymentCreation(async context => { + console.log("🔍 [BeforePaymentCreation] Creating payment for:"); + console.log(` Network: ${context.selectedRequirements.network}`); + console.log(` Scheme: ${context.selectedRequirements.scheme}`); + console.log(); + + // You can abort payment creation by returning: + // return { abort: true, reason: "Payment not allowed for this resource" }; + }) + .onAfterPaymentCreation(async context => { + console.log("✅ [AfterPaymentCreation] Payment created successfully"); + console.log(` Version: ${context.paymentPayload.x402Version}`); + console.log(); + + // Perform side effects like logging to database, sending metrics, etc. + // Errors here are logged but don't fail the payment + }) + .onPaymentCreationFailure(async context => { + console.log(`❌ [OnPaymentCreationFailure] Payment creation failed: ${context.error}`); + console.log(); + + // You could attempt to recover by providing an alternative payload: + // return { recovered: true, payload: alternativePayload }; + }); + + const { wrapFetchWithPayment } = await import("@x402/fetch"); + const fetchWithPayment = wrapFetchWithPayment(fetch, client); + + console.log(`🌐 Making request to: ${url}\n`); + const response = await fetchWithPayment(url, { method: "GET" }); + const body = await response.json(); + + console.log("✅ Request completed successfully with hooks\n"); + console.log("Response body:", body); + + // Extract payment response from headers + const { x402HTTPClient } = await import("@x402/fetch"); + const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => + response.headers.get(name), + ); + if (paymentResponse) { + console.log("\n💰 Payment Details:", paymentResponse); + } +} diff --git a/examples/typescript/clients/advanced/index.ts b/examples/typescript/clients/advanced/index.ts new file mode 100644 index 000000000..0b06b38ad --- /dev/null +++ b/examples/typescript/clients/advanced/index.ts @@ -0,0 +1,62 @@ +import { config } from "dotenv"; +import { runHooksExample } from "./hooks"; +import { runPreferredNetworkExample } from "./preferred-network"; + +config(); + +const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}`; +const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string; +const baseURL = process.env.RESOURCE_SERVER_URL || "http://localhost:4021"; +const endpointPath = process.env.ENDPOINT_PATH || "/weather"; +const url = `${baseURL}${endpointPath}`; + +/** + * Main example runner for advanced x402 client patterns. + * + * This package demonstrates advanced patterns for production-ready x402 clients: + * + * - hooks: Payment lifecycle hooks for custom logic at different stages + * - preferred-network: Client-side payment network preferences + * + * To run this example, you need to set the following environment variables: + * - EVM_PRIVATE_KEY: The private key of the EVM signer + * - SVM_PRIVATE_KEY: The private key of the SVM signer + * + * Usage: + * npm start hooks + * npm start preferred-network + */ +async function main(): Promise { + const pattern = process.argv[2] || "hooks"; + + console.log(`\n🚀 Running advanced example: ${pattern}\n`); + + if (!evmPrivateKey) { + console.error("❌ EVM_PRIVATE_KEY environment variable is required"); + process.exit(1); + } + + switch (pattern) { + case "hooks": + await runHooksExample(evmPrivateKey, url); + break; + + case "preferred-network": + if (!svmPrivateKey) { + console.error("❌ SVM_PRIVATE_KEY environment variable is required for preferred-network"); + process.exit(1); + } + await runPreferredNetworkExample(evmPrivateKey, svmPrivateKey, url); + break; + + default: + console.error(`Unknown pattern: ${pattern}`); + console.error("Available patterns: hooks, preferred-network"); + process.exit(1); + } +} + +main().catch(error => { + console.error(error?.response?.data?.error ?? error); + process.exit(1); +}); diff --git a/examples/typescript/clients/advanced/package.json b/examples/typescript/clients/advanced/package.json new file mode 100644 index 000000000..260b7a937 --- /dev/null +++ b/examples/typescript/clients/advanced/package.json @@ -0,0 +1,36 @@ +{ + "name": "@x402/advanced-client-example", + "private": true, + "type": "module", + "scripts": { + "start": "tsx index.ts", + "dev": "tsx index.ts hooks", + "dev:hooks": "tsx index.ts hooks", + "dev:preferred-network": "tsx index.ts preferred-network", + "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", + "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", + "lint": "eslint . --ext .ts --fix", + "lint:check": "eslint . --ext .ts" + }, + "dependencies": { + "@scure/base": "^1.2.6", + "@x402/evm": "workspace:*", + "@x402/svm": "workspace:*", + "@x402/fetch": "workspace:*", + "dotenv": "^16.4.7", + "viem": "^2.39.0", + "@solana/kit": "^2.1.1" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "eslint": "^9.24.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", + "prettier": "3.5.2", + "tsx": "^4.7.0", + "typescript": "^5.3.0" + } +} diff --git a/examples/typescript/clients/advanced/preferred-network.ts b/examples/typescript/clients/advanced/preferred-network.ts new file mode 100644 index 000000000..b22ae4ead --- /dev/null +++ b/examples/typescript/clients/advanced/preferred-network.ts @@ -0,0 +1,93 @@ +import { privateKeyToAccount } from "viem/accounts"; +import { x402Client, type PaymentRequirements } from "@x402/fetch"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { ExactSvmScheme } from "@x402/svm/exact/client"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; +import { x402HTTPClient, wrapFetchWithPayment } from "@x402/fetch"; + +/** + * Preferred Network Example + * + * This demonstrates how to configure client-side payment option preferences. + * The client can specify which network/scheme it prefers, with automatic + * fallback to other supported options if the preferred one isn't available. + * + * Use cases: + * - Prefer specific networks or chains + * - User preference settings in a wallet UI + * + * @param evmPrivateKey - The EVM private key for signing + * @param svmPrivateKey - The SVM private key for signing + * @param url - The URL to make the request to + */ +export async function runPreferredNetworkExample( + evmPrivateKey: `0x${string}`, + svmPrivateKey: string, + url: string, +): Promise { + console.log("🎯 Creating client with preferred network selection...\n"); + + const evmSigner = privateKeyToAccount(evmPrivateKey); + const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey)); + + // Define network preference order (most preferred first) + const networkPreferences = ["solana:", "eip155:"]; + + /** + * Custom selector that picks payment options based on preference order. + * + * NOTE: By the time this selector is called, `options` has already been + * filtered to only include options that BOTH the server offers AND the + * client has registered support for. So fallback to options[0] means + * "first mutually-supported option" (which preserves server's preference order). + * + * @param _x402Version - The x402 protocol version + * @param options - Array of mutually supported payment options + * @returns The selected payment requirement based on network preference + */ + const preferredNetworkSelector = ( + _x402Version: number, + options: PaymentRequirements[], + ): PaymentRequirements => { + console.log("📋 Mutually supported payment options (server offers + client supports):"); + options.forEach((opt, i) => { + console.log(` ${i + 1}. ${opt.network} (${opt.scheme})`); + }); + console.log(); + + // Try each preference in order + for (const preference of networkPreferences) { + const match = options.find(opt => opt.network.startsWith(preference)); + if (match) { + console.log(`✨ Selected preferred network: ${match.network}`); + return match; + } + } + + // Fallback to first mutually-supported option (server's top preference among what we support) + console.log(`⚠️ No preferred network available, falling back to: ${options[0].network}`); + return options[0]; + }; + + const client = new x402Client(preferredNetworkSelector) + .register("eip155:*", new ExactEvmScheme(evmSigner)) + .register("solana:*", new ExactSvmScheme(svmSigner)); + + const fetchWithPayment = wrapFetchWithPayment(fetch, client); + + console.log(`🌐 Making request to: ${url}\n`); + const response = await fetchWithPayment(url, { method: "GET" }); + const body = await response.json(); + + console.log("✅ Request completed successfully\n"); + console.log("Response body:", body); + + // Extract payment response from headers + const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => + response.headers.get(name), + ); + if (paymentResponse) { + console.log("\n💰 Payment Details:", paymentResponse); + } +} diff --git a/examples/typescript/clients/advanced/tsconfig.json b/examples/typescript/clients/advanced/tsconfig.json new file mode 100644 index 000000000..78f9479b1 --- /dev/null +++ b/examples/typescript/clients/advanced/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "strict": true, + "resolveJsonModule": true, + "baseUrl": ".", + "types": ["node"] + }, + "include": ["index.ts"] +} diff --git a/examples/typescript/clients/axios/.env-local b/examples/typescript/clients/axios/.env-local index 3d2e1855d..8339ac0ab 100644 --- a/examples/typescript/clients/axios/.env-local +++ b/examples/typescript/clients/axios/.env-local @@ -1,3 +1,4 @@ +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= RESOURCE_SERVER_URL=http://localhost:4021 -ENDPOINT_PATH=/weather -PRIVATE_KEY= +ENDPOINT_PATH=/weather \ No newline at end of file diff --git a/examples/typescript/clients/axios/README.md b/examples/typescript/clients/axios/README.md index 4bb308ba9..27d9411f7 100644 --- a/examples/typescript/clients/axios/README.md +++ b/examples/typescript/clients/axios/README.md @@ -1,80 +1,76 @@ # x402-axios Example Client -This is an example client that demonstrates how to use the `x402-axios` package to make HTTP requests to endpoints protected by the x402 payment protocol. +Example client demonstrating how to use `@x402/axios` to make HTTP requests to endpoints protected by the x402 payment protocol. ## Prerequisites - Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) - pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) -- A running x402 server (you can use the example express server at `examples/typescript/servers/express`) -- A valid Ethereum private key for making payments +- A running x402 server (see [express server example](../../servers/express)) +- Valid EVM and/or SVM private keys for making payments ## Setup 1. Install and build all packages from the typescript examples root: ```bash cd ../../ -pnpm install -pnpm build +pnpm install && pnpm build cd clients/axios ``` -2. Copy `.env-local` to `.env` and add your Ethereum private key (remember it should have USDC on Base Sepolia, which you can provision using the [CDP Faucet](https://portal.cdp.coinbase.com/products/faucet)): +2. Copy `.env-local` to `.env` and add your private keys: ```bash cp .env-local .env ``` -3. Start the example client (remember you need to be running a server locally or point at an endpoint): +Required environment variables: +- `EVM_PRIVATE_KEY` - Ethereum private key for EVM payments +- `SVM_PRIVATE_KEY` - Solana private key for SVM payments + +3. Run the client: ```bash -pnpm dev +pnpm start ``` -## How It Works +## Available Examples + +### 1. Builder Pattern (`builder-pattern`) +Configure the client by chaining `.register()` calls to map scheme patterns to mechanism clients. + +```bash +pnpm start builder-pattern +``` -The example demonstrates how to: -1. Create a wallet client using viem -2. Create an Axios instance with x402 payment handling -3. Make a request to a paid endpoint -4. Handle the response or any errors +### 2. Mechanism Helper Registration (`mechanism-helper-registration`) +Use convenience helper functions from `@x402/evm` and `@x402/svm` to register supported networks. + +```bash +pnpm start mechanism-helper-registration +``` ## Example Code ```typescript -import { config } from "dotenv"; -import { createWalletClient, http, publicActions } from "viem"; +import { x402Client, wrapAxiosWithPayment } from "@x402/axios"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; -import { withPaymentInterceptor } from "x402-axios"; import axios from "axios"; -import { baseSepolia } from "viem/chains"; - -config(); -const { RESOURCE_SERVER_URL, PRIVATE_KEY, ENDPOINT_PATH } = process.env; +// Create signer +const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY); -// Create wallet client -const account = privateKeyToAccount(PRIVATE_KEY as "0x${string}"); -const client = createWalletClient({ - account, - transport: http(), - chain: baseSepolia, -}).extend(publicActions); +// Configure client with builder pattern +const client = new x402Client() + .register("eip155:*", new ExactEvmScheme(signer)); -// Create Axios instance with payment handling -const api = withPaymentInterceptor( - axios.create({ - baseURL: RESOURCE_SERVER_URL, - }), - client -); +// Wrap axios with payment handling +const api = wrapAxiosWithPayment(axios.create(), client); // Make request to paid endpoint -api - .get(ENDPOINT_PATH) - .then(response => { - console.log(response.headers); - console.log(response.data); - }) - .catch(error => { - console.error(error.response?.data?.error); - }); +const response = await api.get("http://localhost:4021/weather"); +console.log(response.data); ``` + +## Next Steps + +See [Advanced Examples](../advanced/) for payment lifecycle hooks and setting network preferences. diff --git a/examples/typescript/clients/axios/builder-pattern.ts b/examples/typescript/clients/axios/builder-pattern.ts new file mode 100644 index 000000000..4b90579b7 --- /dev/null +++ b/examples/typescript/clients/axios/builder-pattern.ts @@ -0,0 +1,37 @@ +import { privateKeyToAccount } from "viem/accounts"; +import { x402Client } from "@x402/axios"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { ExactSvmScheme } from "@x402/svm/exact/client"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; + +/** + * Creates an x402Client using the builder pattern to register schemes. + * + * This demonstrates the basic way to configure the client by chaining + * registerScheme calls to map scheme patterns to mechanism clients. + * + * @param evmPrivateKey - The EVM private key for signing transactions + * @param svmPrivateKey - The SVM private key for signing transactions + * @returns A configured x402Client instance + */ +export async function createBuilderPatternClient( + evmPrivateKey: `0x${string}`, + svmPrivateKey: string, +): Promise { + const evmSigner = privateKeyToAccount(evmPrivateKey); + const ethereumSigner = evmSigner; // Say you wanted a different signer for Ethereum Mainnet + const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey)); + const solanaDevnetSigner = svmSigner; // Say you wanted a different signer for Solana Devnet + + const client = new x402Client() + .register("eip155:*", new ExactEvmScheme(evmSigner)) + .register("eip155:1", new ExactEvmScheme(ethereumSigner)) + .register("solana:*", new ExactSvmScheme(svmSigner)) + .register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", new ExactSvmScheme(solanaDevnetSigner)); + + // The result is a specific signer for Ethereum mainnet & Solana devnet + // Falling back to a generic signer for all other evm & solana networks + + return client; +} diff --git a/examples/typescript/clients/axios/index.ts b/examples/typescript/clients/axios/index.ts index 2f03b5889..a3a322446 100644 --- a/examples/typescript/clients/axios/index.ts +++ b/examples/typescript/clients/axios/index.ts @@ -1,46 +1,72 @@ -import axios from "axios"; import { config } from "dotenv"; -import { withPaymentInterceptor, decodeXPaymentResponse, createSigner, type Hex } from "x402-axios"; +import { wrapAxiosWithPayment, x402HTTPClient } from "@x402/axios"; +import { createBuilderPatternClient } from "./builder-pattern"; +import { createMechanismHelperClient } from "./mechanism-helper-registration"; +import axios from "axios"; config(); -const privateKey = process.env.PRIVATE_KEY as Hex | string; -const baseURL = process.env.RESOURCE_SERVER_URL as string; // e.g. https://example.com -const endpointPath = process.env.ENDPOINT_PATH as string; // e.g. /weather - -if (!baseURL || !privateKey || !endpointPath) { - console.error("Missing required environment variables"); - process.exit(1); -} +const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}`; +const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string; +const baseURL = process.env.RESOURCE_SERVER_URL || "http://localhost:4021"; +const endpointPath = process.env.ENDPOINT_PATH || "/weather"; +const url = `${baseURL}${endpointPath}`; /** - * This example shows how to use the x402-axios package to make a request to a resource server that requires a payment. + * Main example runner for @x402/axios package demonstrations. + * + * This example shows how to use the @x402/axios package to make a request + * to a resource server that requires a payment. Different client creation + * patterns can be selected via CLI argument: + * + * - builder-pattern: Basic builder pattern with registerScheme + * - mechanism-helper-registration: Using helper functions for registration * * To run this example, you need to set the following environment variables: - * - PRIVATE_KEY: The private key of the signer - * - RESOURCE_SERVER_URL: The URL of the resource server - * - ENDPOINT_PATH: The path of the endpoint to call on the resource server + * - EVM_PRIVATE_KEY: The private key of the EVM signer + * - SVM_PRIVATE_KEY: The private key of the SVM signer * + * Usage: + * npm start builder-pattern + * npm start mechanism-helper-registration */ async function main(): Promise { - // const signer = await createSigner("solana-devnet", privateKey); // uncomment for solana - const signer = await createSigner("base-sepolia", privateKey); - - const api = withPaymentInterceptor( - axios.create({ - baseURL, - }), - signer, - ); - - const response = await api.get(endpointPath); - console.log(response.data); - - const paymentResponseHeader = response.headers["x-payment-response"]; - if (paymentResponseHeader) { - const paymentResponse = decodeXPaymentResponse(paymentResponseHeader); - console.log(paymentResponse); + const pattern = process.argv[2] || "builder-pattern"; + + console.log(`\nRunning example: ${pattern}\n`); + + let client; + switch (pattern) { + case "builder-pattern": + client = await createBuilderPatternClient(evmPrivateKey, svmPrivateKey); + break; + case "mechanism-helper-registration": + client = await createMechanismHelperClient(evmPrivateKey, svmPrivateKey); + break; + default: + console.error(`Unknown pattern: ${pattern}`); + console.error("Available patterns: builder-pattern, mechanism-helper-registration"); + process.exit(1); + } + + const api = wrapAxiosWithPayment(axios.create(), client); + + console.log(`Making request to: ${url}\n`); + const response = await api.get(url); + const body = response.data; + console.log("Response body:", body); + + if (response.status < 400) { + const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse( + name => response.headers[name.toLowerCase()], + ); + console.log("\nPayment response:", paymentResponse); + } else { + console.log(`\nNo payment settled (response status: ${response.status})`); } } -main(); +main().catch(error => { + console.error(error?.response?.data?.error ?? error); + process.exit(1); +}); diff --git a/examples/typescript/clients/axios/mechanism-helper-registration.ts b/examples/typescript/clients/axios/mechanism-helper-registration.ts new file mode 100644 index 000000000..7868c26fe --- /dev/null +++ b/examples/typescript/clients/axios/mechanism-helper-registration.ts @@ -0,0 +1,35 @@ +import { privateKeyToAccount } from "viem/accounts"; +import { x402Client } from "@x402/axios"; +import { registerExactEvmScheme } from "@x402/evm/exact/client"; +import { registerExactSvmScheme } from "@x402/svm/exact/client"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; + +/** + * Creates an x402Client using helper functions for registration. + * + * This demonstrates using the convenience helper functions provided by + * the @x402/evm and @x402/svm packages. These helpers register all EVM + * networks in v2 (eip155:*) and all v1 networks for backwards compatibility, + * and similarly for SVM networks (solana:*). + * + * @param evmPrivateKey - The EVM private key for signing transactions + * @param svmPrivateKey - The SVM private key for signing transactions + * @returns A configured x402Client instance + */ +export async function createMechanismHelperClient( + evmPrivateKey: `0x${string}`, + svmPrivateKey: string, +): Promise { + const evmSigner = privateKeyToAccount(evmPrivateKey); + const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey)); + + const client = new x402Client(); + + // Helper that registers all EVM networks in v2 (eip155:*) and all v1 networks for backwards compatibility + registerExactEvmScheme(client, { signer: evmSigner }); + // Helper that registers all SVM networks in v2 (solana:*) and all v1 networks for backwards compatibility + registerExactSvmScheme(client, { signer: svmSigner }); + + return client; +} diff --git a/examples/typescript/clients/axios/package.json b/examples/typescript/clients/axios/package.json index 8d2f89bdb..6a1e796ff 100644 --- a/examples/typescript/clients/axios/package.json +++ b/examples/typescript/clients/axios/package.json @@ -1,19 +1,26 @@ { - "name": "axios-client-example", + "name": "@x402/axios-client-example", "private": true, "type": "module", "scripts": { - "dev": "tsx index.ts", - "dev:multi-network-signer": "tsx multi-network-signer.ts", + "start": "tsx index.ts", + "dev": "tsx index.ts builder-pattern", + "dev:hooks": "tsx index.ts hooks", + "dev:mechanism-helper-registration": "tsx index.ts mechanism-helper-registration", "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", "lint": "eslint . --ext .ts --fix", "lint:check": "eslint . --ext .ts" }, "dependencies": { - "axios": "^1.7.9", - "dotenv": "^16.5.0", - "x402-axios": "workspace:*" + "@scure/base": "^1.2.6", + "@solana/kit": "^2.1.1", + "@x402/axios": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/svm": "workspace:*", + "axios": "^1.13.2", + "dotenv": "^16.4.7", + "viem": "^2.39.0" }, "devDependencies": { "@eslint/js": "^9.24.0", diff --git a/examples/typescript/clients/custom/.env-local b/examples/typescript/clients/custom/.env-local new file mode 100644 index 000000000..8339ac0ab --- /dev/null +++ b/examples/typescript/clients/custom/.env-local @@ -0,0 +1,4 @@ +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= +RESOURCE_SERVER_URL=http://localhost:4021 +ENDPOINT_PATH=/weather \ No newline at end of file diff --git a/examples/typescript/mcp/.prettierrc b/examples/typescript/clients/custom/.prettierrc similarity index 100% rename from examples/typescript/mcp/.prettierrc rename to examples/typescript/clients/custom/.prettierrc diff --git a/examples/typescript/clients/custom/README.md b/examples/typescript/clients/custom/README.md new file mode 100644 index 000000000..466ab5365 --- /dev/null +++ b/examples/typescript/clients/custom/README.md @@ -0,0 +1,164 @@ +# Custom x402 Client Implementation + +Express.js client demonstrating how to implement x402 payment handling manually using only the core packages, without convenience wrappers like `@x402/fetch` or `@x402/axios`. + +## Prerequisites + +- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) +- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) +- Valid EVM and SVM private keys for making payments +- A running x402 server (see [server examples](../../servers/)) + +## Setup + +1. Copy `.env-local` to `.env`: + +```bash +cp .env-local .env +``` + +and fill required environment variables: + +- `EVM_PRIVATE_KEY` - Ethereum private key for EVM payments +- `SVM_PRIVATE_KEY` - Solana private key for SVM payments + +2. Install and build all packages from the typescript examples root: + +```bash +cd ../../ +pnpm install && pnpm build +cd clients/custom +``` + +3. Run the example + +```bash +pnpm dev +``` + +## Testing the Example + +Start a server first: + +```bash +cd ../../servers/express +pnpm dev +``` + +Then run the custom client: + +```bash +cd ../../clients/custom +pnpm dev +``` + +## HTTP Headers (v2 Protocol) + +| Header | Direction | Description | +| ------------------- | --------------- | -------------------------------------- | +| `PAYMENT-REQUIRED` | Server → Client | 402 response with payment requirements | +| `PAYMENT-SIGNATURE` | Client → Server | Retry request with payment payload | +| `PAYMENT-RESPONSE` | Server → Client | 200 response with settlement details | + +## Payment Flow + +1. **Initial Request** — Make HTTP request to protected endpoint +2. **402 Response** — Server responds with requirements in `PAYMENT-REQUIRED` header +3. **Parse Requirements** — Decode requirements using `decodePaymentRequiredHeader()` +4. **Create Payment** — Use `x402Client.createPaymentPayload()` to generate payload +5. **Encode Payment** — Use `encodePaymentSignatureHeader()` for the header value +6. **Retry with Payment** — Make new request with `PAYMENT-SIGNATURE` header +7. **Success** — Receive 200 with settlement in `PAYMENT-RESPONSE` header + +## Key Implementation Details + +### 1. Setting Up the Client + +```typescript +import { x402Client } from "@x402/core/client"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { ExactSvmScheme } from "@x402/svm/exact/client"; +import { privateKeyToAccount } from "viem/accounts"; + +const evmSigner = privateKeyToAccount(evmPrivateKey); +const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey)); + +// Optional: custom selector to pick which payment option to use +const selectPayment = (_version: number, requirements: PaymentRequirements[]) => { + return requirements[1]; // Select second option (e.g., Solana) +}; + +const client = new x402Client(selectPayment) + .register("eip155:*", new ExactEvmScheme(evmSigner)) + .register("solana:*", new ExactSvmScheme(svmSigner)); +``` + +### 2. Detecting Payment Required + +```typescript +import { decodePaymentRequiredHeader } from "@x402/core/http"; + +if (response.status === 402) { + const paymentRequiredHeader = response.headers.get("PAYMENT-REQUIRED"); + const paymentRequired = decodePaymentRequiredHeader(paymentRequiredHeader); + // paymentRequired.accepts contains the payment options +} +``` + +### 3. Creating Payment Payload + +```typescript +import { encodePaymentSignatureHeader } from "@x402/core/http"; + +const paymentPayload = await client.createPaymentPayload(paymentRequired); +const paymentHeader = encodePaymentSignatureHeader(paymentPayload); +``` + +### 4. Retrying with Payment + +```typescript +const response = await fetch(url, { + headers: { + "PAYMENT-SIGNATURE": paymentHeader, + }, +}); +``` + +### 5. Extracting Settlement + +```typescript +import { decodePaymentResponseHeader } from "@x402/core/http"; + +const settlementHeader = response.headers.get("PAYMENT-RESPONSE"); +const settlement = decodePaymentResponseHeader(settlementHeader); +// settlement.transaction, settlement.network, settlement.payer +``` + +## Wrapper vs Custom Comparison + +| Aspect | With Wrapper (@x402/fetch) | Custom Implementation | +| ----------------- | -------------------------- | --------------------- | +| Code Complexity | ~10 lines | ~100 lines | +| Automatic Retry | ✅ Yes | ❌ Manual | +| Error Handling | ✅ Built-in | ❌ You implement | +| Header Management | ✅ Automatic | ❌ Manual | +| Flexibility | Limited | ✅ Complete control | + +## When to Use Custom Implementation + +- Need complete control over every step of the payment flow +- Integrating with non-standard HTTP libraries +- Implementing custom retry/error logic +- Learning how x402 works under the hood + +## Adapting to Other HTTP Clients + +To use this pattern with other HTTP clients (axios, got, etc.): + +1. Detect 402 status code +2. Extract requirements from `PAYMENT-REQUIRED` header +3. Use `decodePaymentRequiredHeader()` to parse +4. Use `x402Client.createPaymentPayload()` to create payload +5. Use `encodePaymentSignatureHeader()` to encode +6. Add `PAYMENT-SIGNATURE` header to retry request +7. Extract settlement from `PAYMENT-RESPONSE` header diff --git a/typescript/packages/x402-axios/eslint.config.js b/examples/typescript/clients/custom/eslint.config.js similarity index 100% rename from typescript/packages/x402-axios/eslint.config.js rename to examples/typescript/clients/custom/eslint.config.js diff --git a/examples/typescript/clients/custom/index.ts b/examples/typescript/clients/custom/index.ts new file mode 100644 index 000000000..16ab38403 --- /dev/null +++ b/examples/typescript/clients/custom/index.ts @@ -0,0 +1,134 @@ +import { config } from "dotenv"; +import { privateKeyToAccount } from "viem/accounts"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; +import { x402Client } from "@x402/core/client"; +import { + decodePaymentRequiredHeader, + decodePaymentResponseHeader, + encodePaymentSignatureHeader, +} from "@x402/core/http"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { ExactSvmScheme } from "@x402/svm/exact/client"; +import type { PaymentRequirements } from "@x402/core/types"; + +config(); + +/** + * Custom x402 Client Implementation (v2 Protocol) + * + * This example demonstrates how to implement x402 payment handling manually + * using only the core packages, without the convenience wrappers like @x402/fetch. + * + * x402 v2 Protocol Headers: + * - PAYMENT-REQUIRED: Server → Client (402 response) + * - PAYMENT-SIGNATURE: Client → Server (retry with payment) + * - PAYMENT-RESPONSE: Server → Client (settlement confirmation) + */ + +const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}`; +const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string; +const baseURL = process.env.SERVER_URL || "http://localhost:4021"; +const url = `${baseURL}/weather`; + +/** + * Makes a request with x402 payment handling. + * + * @param client - The x402 client instance to use for payments + * @param url - The URL to request + */ +async function makeRequestWithPayment(client: x402Client, url: string): Promise { + console.log(`\n🌐 Making initial request to: ${url}\n`); + + // Step 1: Make initial request + let response = await fetch(url); + console.log(`📥 Initial response status: ${response.status}\n`); + + // Step 2: Handle 402 Payment Required + if (response.status === 402) { + console.log("💳 Payment required! Processing...\n"); + + // Decode payment requirements from PAYMENT-REQUIRED header + const paymentRequiredHeader = response.headers.get("PAYMENT-REQUIRED"); + if (!paymentRequiredHeader) { + throw new Error("Missing PAYMENT-REQUIRED header"); + } + const paymentRequired = decodePaymentRequiredHeader(paymentRequiredHeader); + + const requirements: PaymentRequirements[] = Array.isArray(paymentRequired.accepts) + ? paymentRequired.accepts + : [paymentRequired.accepts]; + + console.log("📋 Payment requirements:"); + requirements.forEach((req, i) => { + console.log(` ${i + 1}. ${req.network} / ${req.scheme} - ${req.amount}`); + }); + + // Step 3: Create and encode payment + console.log("\n🔐 Creating payment...\n"); + const paymentPayload = await client.createPaymentPayload(paymentRequired); + const paymentHeader = encodePaymentSignatureHeader(paymentPayload); + + // Step 4: Retry with PAYMENT-SIGNATURE header + console.log("🔄 Retrying with payment...\n"); + response = await fetch(url, { + headers: { "PAYMENT-SIGNATURE": paymentHeader }, + }); + console.log(`📥 Response status: ${response.status}\n`); + } + + // Step 5: Handle success + if (response.status === 200) { + console.log("✅ Success!\n"); + console.log("Response:", await response.json()); + + // Decode settlement from PAYMENT-RESPONSE header + const settlementHeader = response.headers.get("PAYMENT-RESPONSE"); + if (settlementHeader) { + const settlement = decodePaymentResponseHeader(settlementHeader); + console.log("\n💰 Settlement:"); + console.log(` Transaction: ${settlement.transaction}`); + console.log(` Network: ${settlement.network}`); + console.log(` Payer: ${settlement.payer}`); + } + } else { + throw new Error(`Unexpected status: ${response.status}`); + } +} + +/** + * Main entry point demonstrating custom x402 client usage. + */ +async function main(): Promise { + console.log("\n🔧 Custom x402 Client (v2 Protocol)\n"); + + if (!evmPrivateKey) { + console.error("❌ EVM_PRIVATE_KEY required"); + process.exit(1); + } + + const evmSigner = privateKeyToAccount(evmPrivateKey); + const solanaSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey)); + + // Custom selector - pick which payment option to use + // This selects the second payment option (Solana) + // Create your own logic here to select preferred payment option + const selectPayment = (_version: number, requirements: PaymentRequirements[]) => { + const selected = requirements[1]; + console.log(`🎯 Selected: ${selected.network} / ${selected.scheme}`); + return selected; + }; + + const client = new x402Client(selectPayment) + .register("eip155:*", new ExactEvmScheme(evmSigner)) + .register("solana:*", new ExactSvmScheme(solanaSigner)); + console.log("✅ Client ready\n"); + + await makeRequestWithPayment(client, url); + console.log("\n🎉 Done!"); +} + +main().catch(error => { + console.error("\n❌ Error:", error.message); + process.exit(1); +}); diff --git a/examples/typescript/clients/custom/package.json b/examples/typescript/clients/custom/package.json new file mode 100644 index 000000000..d8fc63079 --- /dev/null +++ b/examples/typescript/clients/custom/package.json @@ -0,0 +1,34 @@ +{ + "name": "@x402/custom-client-example", + "private": true, + "type": "module", + "scripts": { + "start": "tsx index.ts", + "dev": "tsx index.ts", + "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", + "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", + "lint": "eslint . --ext .ts --fix", + "lint:check": "eslint . --ext .ts" + }, + "dependencies": { + "@scure/base": "^1.2.6", + "@solana/kit": "^2.1.1", + "@x402/core": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/svm": "workspace:*", + "dotenv": "^16.4.7", + "viem": "^2.39.0" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@typescript-eslint/eslint-plugin": "^8.29.1", + "@typescript-eslint/parser": "^8.29.1", + "eslint": "^9.24.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", + "prettier": "3.5.2", + "tsx": "^4.7.0", + "typescript": "^5.3.0" + } +} diff --git a/examples/typescript/clients/custom/tsconfig.json b/examples/typescript/clients/custom/tsconfig.json new file mode 100644 index 000000000..78f9479b1 --- /dev/null +++ b/examples/typescript/clients/custom/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "strict": true, + "resolveJsonModule": true, + "baseUrl": ".", + "types": ["node"] + }, + "include": ["index.ts"] +} diff --git a/examples/typescript/clients/fetch/.env-local b/examples/typescript/clients/fetch/.env-local index 3d2e1855d..8339ac0ab 100644 --- a/examples/typescript/clients/fetch/.env-local +++ b/examples/typescript/clients/fetch/.env-local @@ -1,3 +1,4 @@ +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= RESOURCE_SERVER_URL=http://localhost:4021 -ENDPOINT_PATH=/weather -PRIVATE_KEY= +ENDPOINT_PATH=/weather \ No newline at end of file diff --git a/examples/typescript/clients/fetch/README.md b/examples/typescript/clients/fetch/README.md index f04ed5516..65c198e64 100644 --- a/examples/typescript/clients/fetch/README.md +++ b/examples/typescript/clients/fetch/README.md @@ -1,75 +1,76 @@ # x402-fetch Example Client -This is an example client that demonstrates how to use the `x402-fetch` package to make HTTP requests to endpoints protected by the x402 payment protocol. +Example client demonstrating how to use `@x402/fetch` to make HTTP requests to endpoints protected by the x402 payment protocol. ## Prerequisites - Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) - pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) -- A running x402 server (you can use the example express server at `examples/typescript/servers/express`) -- A valid Ethereum private key for making payments +- A running x402 server (see [express server example](../../servers/express)) +- Valid EVM and/or SVM private keys for making payments ## Setup 1. Install and build all packages from the typescript examples root: ```bash cd ../../ -pnpm install -pnpm build +pnpm install && pnpm build cd clients/fetch ``` -2. Copy `.env-local` to `.env` and add your Ethereum private key: +2. Copy `.env-local` to `.env` and add your private keys: ```bash cp .env-local .env ``` -3. Start the example client: +Required environment variables: +- `EVM_PRIVATE_KEY` - Ethereum private key for EVM payments +- `SVM_PRIVATE_KEY` - Solana private key for SVM payments + +3. Run the client: ```bash -pnpm dev +pnpm start ``` -## How It Works +## Available Examples + +### 1. Builder Pattern (`builder-pattern`) +Configure the client by chaining `.register()` calls to map scheme patterns to mechanism clients. + +```bash +pnpm start builder-pattern +``` -The example demonstrates how to: -1. Create a wallet client using viem -2. Wrap the native fetch function with x402 payment handling -3. Make a request to a paid endpoint -4. Handle the response or any errors +### 2. Mechanism Helper Registration (`mechanism-helper-registration`) +Use convenience helper functions from `@x402/evm` and `@x402/svm` to register supported networks. + +```bash +pnpm start mechanism-helper-registration +``` ## Example Code ```typescript -import { config } from "dotenv"; -import { createWalletClient, http } from "viem"; +import { x402Client, wrapFetchWithPayment } from "@x402/fetch"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; -import { wrapFetchWithPayment } from "x402-fetch"; -import { baseSepolia } from "viem/chains"; - -config(); -const { RESOURCE_SERVER_URL, PRIVATE_KEY, ENDPOINT_PATH } = process.env; +// Create signer +const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY); -// Create wallet client -const account = privateKeyToAccount(PRIVATE_KEY as `0x${string}`); -const client = createWalletClient({ - account, - transport: http(), - chain: baseSepolia, -}); +// Configure client with builder pattern +const client = new x402Client() + .register("eip155:*", new ExactEvmScheme(signer)); // Wrap fetch with payment handling -const fetchWithPay = wrapFetchWithPayment(fetch, client); +const fetchWithPayment = wrapFetchWithPayment(fetch, client); // Make request to paid endpoint -fetchWithPay(`${RESOURCE_SERVER_URL}${ENDPOINT_PATH}`, { - method: "GET", -}) - .then(async response => { - const body = await response.json(); - console.log(body); - }) - .catch(error => { - console.error(error.response?.data?.error); - }); +const response = await fetchWithPayment("http://localhost:4021/weather"); +const body = await response.json(); +console.log(body); ``` + +## Next Steps + +See [Advanced Examples](../advanced/) for payment lifecycle hooks and setting network preferences. diff --git a/examples/typescript/clients/fetch/builder-pattern.ts b/examples/typescript/clients/fetch/builder-pattern.ts new file mode 100644 index 000000000..3cfc42946 --- /dev/null +++ b/examples/typescript/clients/fetch/builder-pattern.ts @@ -0,0 +1,37 @@ +import { privateKeyToAccount } from "viem/accounts"; +import { x402Client } from "@x402/fetch"; +import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { ExactSvmScheme } from "@x402/svm/exact/client"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; + +/** + * Creates an x402Client using the builder pattern to register schemes. + * + * This demonstrates the basic way to configure the client by chaining + * registerScheme calls to map scheme patterns to mechanism clients. + * + * @param evmPrivateKey - The EVM private key for signing transactions + * @param svmPrivateKey - The SVM private key for signing transactions + * @returns A configured x402Client instance + */ +export async function createBuilderPatternClient( + evmPrivateKey: `0x${string}`, + svmPrivateKey: `0x${string}`, +): Promise { + const evmSigner = privateKeyToAccount(evmPrivateKey); + const ethereumSigner = evmSigner; // Say you wanted a different signer for Ethereum Mainnet + const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey)); + const solanaDevnetSigner = svmSigner; // Say you wanted a different signer for Solana Devnet + + const client = new x402Client() + .register("eip155:*", new ExactEvmScheme(evmSigner)) + .register("eip155:1", new ExactEvmScheme(ethereumSigner)) + .register("solana:*", new ExactSvmScheme(svmSigner)) + .register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", new ExactSvmScheme(solanaDevnetSigner)); + + // The result is a specific signer for Ethereum mainnet & Solana devnet + // Falling back to a generic signer for all other evm & solana networks + + return client; +} diff --git a/examples/typescript/clients/fetch/index.ts b/examples/typescript/clients/fetch/index.ts index 2ec607572..6dd98138e 100644 --- a/examples/typescript/clients/fetch/index.ts +++ b/examples/typescript/clients/fetch/index.ts @@ -1,39 +1,67 @@ import { config } from "dotenv"; -import { decodeXPaymentResponse, wrapFetchWithPayment, createSigner, type Hex } from "x402-fetch"; +import { wrapFetchWithPayment, x402HTTPClient } from "@x402/fetch"; +import { createBuilderPatternClient } from "./builder-pattern"; +import { createMechanismHelperClient } from "./mechanism-helper-registration"; config(); -const privateKey = process.env.PRIVATE_KEY as Hex | string; -const baseURL = process.env.RESOURCE_SERVER_URL as string; // e.g. https://example.com -const endpointPath = process.env.ENDPOINT_PATH as string; // e.g. /weather -const url = `${baseURL}${endpointPath}`; // e.g. https://example.com/weather - -if (!baseURL || !privateKey || !endpointPath) { - console.error("Missing required environment variables"); - process.exit(1); -} +const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}`; +const svmPrivateKey = process.env.SVM_PRIVATE_KEY as `0x${string}`; +const baseURL = process.env.RESOURCE_SERVER_URL || "http://localhost:4021"; +const endpointPath = process.env.ENDPOINT_PATH || "/weather"; +const url = `${baseURL}${endpointPath}`; /** - * This example shows how to use the x402-fetch package to make a request to a resource server that requires a payment. + * Main example runner for @x402/fetch package demonstrations. + * + * This example shows how to use the @x402/fetch package to make a request + * to a resource server that requires a payment. Different client creation + * patterns can be selected via CLI argument: + * + * - builder-pattern: Basic builder pattern with registerScheme + * - mechanism-helper-registration: Using helper functions for registration * * To run this example, you need to set the following environment variables: - * - PRIVATE_KEY: The private key of the signer - * - RESOURCE_SERVER_URL: The URL of the resource server - * - ENDPOINT_PATH: The path of the endpoint to call on the resource server + * - EVM_PRIVATE_KEY: The private key of the EVM signer + * - SVM_PRIVATE_KEY: The private key of the SVM signer + * + * Usage: + * npm start builder-pattern + * npm start mechanism-helper-registration */ async function main(): Promise { - // const signer = await createSigner("solana-devnet", privateKey); // uncomment for solana - const signer = await createSigner("base-sepolia", privateKey); - const fetchWithPayment = wrapFetchWithPayment(fetch, signer); + const pattern = process.argv[2] || "builder-pattern"; + + console.log(`\nRunning example: ${pattern}\n`); + + let client; + switch (pattern) { + case "builder-pattern": + client = await createBuilderPatternClient(evmPrivateKey, svmPrivateKey); + break; + case "mechanism-helper-registration": + client = await createMechanismHelperClient(evmPrivateKey, svmPrivateKey); + break; + default: + console.error(`Unknown pattern: ${pattern}`); + console.error("Available patterns: builder-pattern, mechanism-helper-registration"); + process.exit(1); + } + + const fetchWithPayment = wrapFetchWithPayment(fetch, client); + console.log(`Making request to: ${url}\n`); const response = await fetchWithPayment(url, { method: "GET" }); const body = await response.json(); - console.log(body); + console.log("Response body:", body); - const paymentResponseHeader = response.headers.get("x-payment-response"); - if (paymentResponseHeader) { - const paymentResponse = decodeXPaymentResponse(paymentResponseHeader); - console.log(paymentResponse); + if (response.ok) { + const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => + response.headers.get(name), + ); + console.log("\nPayment response:", paymentResponse); + } else { + console.log(`\nNo payment settled (response status: ${response.status})`); } } diff --git a/examples/typescript/clients/fetch/mechanism-helper-registration.ts b/examples/typescript/clients/fetch/mechanism-helper-registration.ts new file mode 100644 index 000000000..49d9f56c4 --- /dev/null +++ b/examples/typescript/clients/fetch/mechanism-helper-registration.ts @@ -0,0 +1,35 @@ +import { privateKeyToAccount } from "viem/accounts"; +import { x402Client } from "@x402/fetch"; +import { registerExactEvmScheme } from "@x402/evm/exact/client"; +import { registerExactSvmScheme } from "@x402/svm/exact/client"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; + +/** + * Creates an x402Client using helper functions for registration. + * + * This demonstrates using the convenience helper functions provided by + * the @x402/evm and @x402/svm packages. These helpers register all EVM + * networks in v2 (eip155:*) and all v1 networks for backwards compatibility, + * and similarly for SVM networks (solana:*). + * + * @param evmPrivateKey - The EVM private key for signing transactions + * @param svmPrivateKey - The SVM private key for signing transactions + * @returns A configured x402Client instance + */ +export async function createMechanismHelperClient( + evmPrivateKey: `0x${string}`, + svmPrivateKey: `0x${string}`, +): Promise { + const evmSigner = privateKeyToAccount(evmPrivateKey); + const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey)); + + const client = new x402Client(); + + // Helper that registers all EVM networks in v2 (eip155:*) and all v1 networks for backwards compatibility + registerExactEvmScheme(client, { signer: evmSigner }); + // Helper that registers all SVM networks in v2 (solana:*) and all v1 networks for backwards compatibility + registerExactSvmScheme(client, { signer: svmSigner }); + + return client; +} diff --git a/examples/typescript/clients/fetch/package.json b/examples/typescript/clients/fetch/package.json index 99cfcda3e..4cced64d6 100644 --- a/examples/typescript/clients/fetch/package.json +++ b/examples/typescript/clients/fetch/package.json @@ -1,18 +1,25 @@ { - "name": "fetch-client-example", + "name": "@x402/fetch-client-example", "private": true, "type": "module", "scripts": { - "dev": "tsx index.ts", - "dev:multi-network-signer": "tsx multi-network-signer.ts", + "start": "tsx index.ts", + "dev": "tsx index.ts builder-pattern", + "dev:hooks": "tsx index.ts hooks", + "dev:mechanism-helper-registration": "tsx index.ts mechanism-helper-registration", "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", "lint": "eslint . --ext .ts --fix", "lint:check": "eslint . --ext .ts" }, "dependencies": { + "@scure/base": "^1.2.6", + "@solana/kit": "^2.1.1", + "@x402/evm": "workspace:*", + "@x402/fetch": "workspace:*", + "@x402/svm": "workspace:*", "dotenv": "^16.4.7", - "x402-fetch": "workspace:*" + "viem": "^2.39.0" }, "devDependencies": { "@eslint/js": "^9.24.0", diff --git a/examples/typescript/discovery/README.md b/examples/typescript/discovery/README.md deleted file mode 100644 index a1159b4dc..000000000 --- a/examples/typescript/discovery/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# x402 Discovery Example - -This example demonstrates how to use the x402 discovery feature to find and list available x402-protected resources across the network. - -## Prerequisites - -- Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) -- pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) - -## Setup - -1. Install and build all packages from the typescript examples root: -```bash -cd ../../ -pnpm install -pnpm build -cd examples/typescript/discovery -``` - -2. Start the discovery example: -```bash -pnpm dev -``` - -## How It Works - -The example demonstrates how to: -1. Use the x402 facilitator to discover available resources -2. List all x402-protected endpoints in the network -3. View detailed information about each resource including: - - Resource URLs - - Last update timestamps - - Accepted payment methods - - Resource metadata - - Protocol versions - -## Example Code - -```typescript -import { useFacilitator } from "x402/verify"; -import { facilitator } from "@coinbase/x402"; - -// No API keys required for discovery -const { list } = useFacilitator(facilitator); - -list().then(response => { - console.log('\nDiscovered X402 Resources:'); - console.log('========================\n'); - - response.items.forEach((item, index) => { - console.log(`Resource ${index + 1}:`); - console.log(` Resource URL: ${item.resource}`); - console.log(` Type: ${item.type}`); - console.log(` Last Updated: ${new Date(item.lastUpdated).toLocaleString()}`); - console.log(` X402 Version: ${item.x402Version}`); - console.log(` Accepts: ${JSON.stringify(item.accepts, null, 2)}`); - if (item.metadata && Object.keys(item.metadata).length > 0) { - console.log(` Metadata: ${JSON.stringify(item.metadata, null, 2)}`); - } - console.log('------------------------\n'); - }); -}); -``` - -## Output Example - -The script will output a formatted list of all discovered x402 resources, including their URLs, types, update times, and accepted payment methods. Example output: - -``` -Discovered X402 Resources: -======================== - -Resource 1: - Resource URL: https://api.example.com/x402/endpoint - Type: http - Last Updated: 8/9/2025, 1:07:04 AM - X402 Version: 1 - Accepts: [Payment Methods] ------------------------- -``` diff --git a/examples/typescript/discovery/index.ts b/examples/typescript/discovery/index.ts deleted file mode 100644 index 77fbdae6f..000000000 --- a/examples/typescript/discovery/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { useFacilitator } from "x402/verify"; -import { facilitator } from "@coinbase/x402"; - -const { list } = useFacilitator(facilitator); - -list().then(response => { - console.log("\nDiscovered X402 Resources:"); - console.log("========================\n"); - - response.items.forEach((item, index) => { - console.log(`Resource ${index + 1}:`); - console.log(` Resource URL: ${item.resource}`); - console.log(` Type: ${item.type}`); - console.log(` Last Updated: ${new Date(item.lastUpdated).toLocaleString()}`); - console.log(` X402 Version: ${item.x402Version}`); - console.log(` Accepts: ${JSON.stringify(item.accepts, null, 2)}`); - if (item.metadata && Object.keys(item.metadata).length > 0) { - console.log(` Metadata: ${JSON.stringify(item.metadata, null, 2)}`); - } - console.log("------------------------\n"); - }); -}); diff --git a/examples/typescript/facilitator/.env-local b/examples/typescript/facilitator/.env-local index 63f7008a1..7534548c3 100644 --- a/examples/typescript/facilitator/.env-local +++ b/examples/typescript/facilitator/.env-local @@ -1,3 +1,3 @@ -EVM_PRIVATE_KEY=0xYourPrivateKey -SVM_PRIVATE_KEY=base58EncodedSolanaPrivateKey -PORT=3002 \ No newline at end of file +PORT= +EVM_PRIVATE_KEY= +SVM_PRIVATE_KEY= \ No newline at end of file diff --git a/examples/typescript/facilitator/README.md b/examples/typescript/facilitator/README.md index 9b8306717..552ba424f 100644 --- a/examples/typescript/facilitator/README.md +++ b/examples/typescript/facilitator/README.md @@ -1,123 +1,221 @@ # x402 Facilitator Example -This is an example implementation of an x402 facilitator service that handles payment verification and settlement for the x402 payment protocol. This implementation is for learning purposes and demonstrates how to build a facilitator service. - -For production use, we recommend using: - -- Testnet: https://x402.org/facilitator -- Production: https://api.cdp.coinbase.com/platform/v2/x402 - -## Overview - -The facilitator provides two main endpoints: - -- `/verify`: Verifies x402 payment payloads -- `/settle`: Settles x402 payments by signing and broadcasting transactions -- `/supported`: Returns the payment kinds that are supported by the facilitator - -This example demonstrates how to: - -1. Set up a basic Express server to handle x402 payment verification and settlement -2. Integrate with the x402 protocol's verification and settlement functions -3. Handle payment payload validation and error cases +Express.js facilitator service that verifies and settles payments on-chain for the x402 protocol. ## Prerequisites - Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) - pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) -- A valid Ethereum private key and/or Solana private key -- Base Sepolia testnet ETH and/or Solana Devnet SOL for transaction fees +- EVM private key with Base Sepolia ETH for transaction fees +- SVM private key with Solana Devnet SOL for transaction fees ## Setup -1. Install and build all packages from the typescript examples root: +1. Copy `.env-local` to `.env`: ```bash -cd .. -pnpm install -pnpm build -cd facilitator +cp .env-local .env ``` -2. Create a `.env` file with the following variables: +and fill required environment variables: + +- `EVM_PRIVATE_KEY` - Ethereum private key +- `SVM_PRIVATE_KEY` - Solana private key +- `PORT` - Server port (optional, defaults to 4022) + +2. Install and build all packages from the typescript examples root: -```env -EVM_PRIVATE_KEY=0xYourPrivateKey -SVM_PRIVATE_KEY=base58EncodedSolanaPrivateKey +```bash +cd ../../ +pnpm install && pnpm build +cd facilitator ``` -3. Start the server: +3. Run the server: ```bash pnpm dev ``` -The server will start on http://localhost:3000 - ## API Endpoints ### GET /supported -Returns information the payment kinds that the facilitator supports. +Returns payment schemes and networks this facilitator supports. -Sample Response +```json +{ + "kinds": [ + { + "x402Version": 2, + "scheme": "exact", + "network": "eip155:84532" + }, + { + "x402Version": 2, + "scheme": "exact", + "network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + "extra": { + "feePayer": "..." + } + } + ], + "extensions": [], + "signers": { + "eip155": ["0x..."], + "solana": ["..."] + } +} +``` -```json5 -[ - { - "x402Version": 1, - "scheme": "exact", - "network": "base-sepolia" - "extra": {} +### POST /verify + +Verifies a payment payload against requirements before settlement. + +Request: + +```json +{ + "paymentPayload": { + "x402Version": 2, + "resource": { + "url": "http://localhost:4021/weather", + "description": "Weather data", + "mimeType": "application/json" + }, + "accepted": { + "scheme": "exact", + "network": "eip155:84532", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "amount": "1000", + "payTo": "0x...", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2" + } + }, + "payload": { + "signature": "0x...", + "authorization": {} + } }, - { - "x402Version": 1, + "paymentRequirements": { "scheme": "exact", - "network": "solana-devnet" + "network": "eip155:84532", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "amount": "1000", + "payTo": "0x...", + "maxTimeoutSeconds": 300, "extra": { - "feePayer": "SolanaAddress" + "name": "USDC", + "version": "2" } - }, -] + } +} ``` -### GET /verify +Response (success): -Returns information about the verify endpoint. +```json +{ + "isValid": true, + "payer": "0x..." +} +``` -### POST /verify +Response (failure): -Verifies an x402 payment payload. +```json +{ + "isValid": false, + "invalidReason": "invalid_signature" +} +``` -Request body: +### POST /settle -```typescript +Settles a verified payment by broadcasting the transaction on-chain. + +Request body is identical to `/verify`. + +Response (success): + +```json +{ + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x..." +} +``` + +Response (failure): + +```json { - payload: string; // x402 payment payload - details: PaymentRequirements; // Payment requirements + "success": false, + "errorReason": "insufficient_balance", + "transaction": "", + "network": "eip155:84532" } ``` -### GET /settle +## Extending the Example -Returns information about the settle endpoint. +### Adding Networks -### POST /settle +Register additional schemes for other networks: + +```typescript +import { registerExactEvmScheme } from "@x402/evm/exact/facilitator"; +import { registerExactSvmScheme } from "@x402/svm/exact/facilitator"; -Settles an x402 payment by signing and broadcasting the transaction. +const facilitator = new x402Facilitator(); -Request body: +registerExactEvmScheme(facilitator, { + signer: evmSigner, + networks: "eip155:84532", +}); + +registerExactSvmScheme(facilitator, { + signer: svmSigner, + networks: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", +}); +``` + +### Lifecycle Hooks + +Add custom logic before/after verify and settle operations: ```typescript -{ - payload: string; // x402 payment payload - details: PaymentRequirements; // Payment requirements -} +const facilitator = new x402Facilitator() + .onBeforeVerify(async (context) => { + // Log or validate before verification + }) + .onAfterVerify(async (context) => { + // Track verified payments + }) + .onVerifyFailure(async (context) => { + // Handle verification failures + }) + .onBeforeSettle(async (context) => { + // Validate before settlement + // Return { abort: true, reason: "..." } to cancel + }) + .onAfterSettle(async (context) => { + // Track successful settlements + }) + .onSettleFailure(async (context) => { + // Handle settlement failures + }); ``` -## Learning Resources +## Network Identifiers -This example is designed to help you understand how x402 facilitators work. For more information about the x402 protocol and its implementation, visit: +Networks use [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) format: -- [x402 Protocol Documentation](https://x402.org) -- [Coinbase Developer Platform](https://www.coinbase.com/developer-platform) +- `eip155:84532` — Base Sepolia +- `eip155:8453` — Base Mainnet +- `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` — Solana Devnet +- `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` — Solana Mainnet diff --git a/examples/typescript/facilitator/eslint.config.js b/examples/typescript/facilitator/eslint.config.js index e2fde7b3b..784ecd543 100644 --- a/examples/typescript/facilitator/eslint.config.js +++ b/examples/typescript/facilitator/eslint.config.js @@ -21,7 +21,6 @@ export default [ module: "readonly", require: "readonly", Buffer: "readonly", - console: "readonly", exports: "readonly", setTimeout: "readonly", clearTimeout: "readonly", @@ -40,7 +39,10 @@ export default [ "import/first": "error", "prettier/prettier": "error", "@typescript-eslint/member-ordering": "error", - "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_$" }], + "@typescript-eslint/no-unused-vars": [ + "error", + { argsIgnorePattern: "^_$" }, + ], "jsdoc/tag-lines": ["error", "any", { startLines: 1 }], "jsdoc/check-alignment": "error", "jsdoc/no-undefined-types": "off", diff --git a/examples/typescript/facilitator/index.ts b/examples/typescript/facilitator/index.ts index 12bf4b59e..a13292833 100644 --- a/examples/typescript/facilitator/index.ts +++ b/examples/typescript/facilitator/index.ts @@ -1,158 +1,236 @@ -/* eslint-env node */ -import { config } from "dotenv"; -import express, { Request, Response } from "express"; -import { verify, settle } from "x402/facilitator"; +import { base58 } from "@scure/base"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { x402Facilitator } from "@x402/core/facilitator"; import { - PaymentRequirementsSchema, - type PaymentRequirements, - type PaymentPayload, - PaymentPayloadSchema, - createConnectedClient, - createSigner, - SupportedEVMNetworks, - SupportedSVMNetworks, - Signer, - ConnectedClient, - SupportedPaymentKind, - isSvmSignerWallet, - type X402Config, -} from "x402/types"; - -config(); - -const EVM_PRIVATE_KEY = process.env.EVM_PRIVATE_KEY || ""; -const SVM_PRIVATE_KEY = process.env.SVM_PRIVATE_KEY || ""; -const SVM_RPC_URL = process.env.SVM_RPC_URL || ""; - -if (!EVM_PRIVATE_KEY && !SVM_PRIVATE_KEY) { - console.error("Missing required environment variables"); + PaymentPayload, + PaymentRequirements, + SettleResponse, + VerifyResponse, +} from "@x402/core/types"; +import { toFacilitatorEvmSigner } from "@x402/evm"; +import { registerExactEvmScheme } from "@x402/evm/exact/facilitator"; +import { toFacilitatorSvmSigner } from "@x402/svm"; +import { registerExactSvmScheme } from "@x402/svm/exact/facilitator"; +import dotenv from "dotenv"; +import express from "express"; +import { createWalletClient, http, publicActions } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { baseSepolia } from "viem/chains"; + +dotenv.config(); + +// Configuration +const PORT = process.env.PORT || "4022"; + +// Validate required environment variables +if (!process.env.EVM_PRIVATE_KEY) { + console.error("❌ EVM_PRIVATE_KEY environment variable is required"); process.exit(1); } -// Create X402 config with custom RPC URL if provided -const x402Config: X402Config | undefined = SVM_RPC_URL - ? { svmConfig: { rpcUrl: SVM_RPC_URL } } - : undefined; - -const app = express(); +if (!process.env.SVM_PRIVATE_KEY) { + console.error("❌ SVM_PRIVATE_KEY environment variable is required"); + process.exit(1); +} -// Configure express to parse JSON bodies -app.use(express.json()); +// Initialize the EVM account from private key +const evmAccount = privateKeyToAccount( + process.env.EVM_PRIVATE_KEY as `0x${string}`, +); +console.info(`EVM Facilitator account: ${evmAccount.address}`); + +// Initialize the SVM account from private key +const svmAccount = await createKeyPairSignerFromBytes( + base58.decode(process.env.SVM_PRIVATE_KEY as string), +); +console.info(`SVM Facilitator account: ${svmAccount.address}`); + +// Create a Viem client with both wallet and public capabilities +const viemClient = createWalletClient({ + account: evmAccount, + chain: baseSepolia, + transport: http(), +}).extend(publicActions); + +// Initialize the x402 Facilitator with EVM and SVM support + +const evmSigner = toFacilitatorEvmSigner({ + getCode: (args: { address: `0x${string}` }) => viemClient.getCode(args), + address: evmAccount.address, + readContract: (args: { + address: `0x${string}`; + abi: readonly unknown[]; + functionName: string; + args?: readonly unknown[]; + }) => + viemClient.readContract({ + ...args, + args: args.args || [], + }), + verifyTypedData: (args: { + address: `0x${string}`; + domain: Record; + types: Record; + primaryType: string; + message: Record; + signature: `0x${string}`; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + }) => viemClient.verifyTypedData(args as any), + writeContract: (args: { + address: `0x${string}`; + abi: readonly unknown[]; + functionName: string; + args: readonly unknown[]; + }) => + viemClient.writeContract({ + ...args, + args: args.args || [], + }), + sendTransaction: (args: { to: `0x${string}`; data: `0x${string}` }) => + viemClient.sendTransaction(args), + waitForTransactionReceipt: (args: { hash: `0x${string}` }) => + viemClient.waitForTransactionReceipt(args), +}); -type VerifyRequest = { - paymentPayload: PaymentPayload; - paymentRequirements: PaymentRequirements; -}; - -type SettleRequest = { - paymentPayload: PaymentPayload; - paymentRequirements: PaymentRequirements; -}; - -app.get("/verify", (req: Request, res: Response) => { - res.json({ - endpoint: "/verify", - description: "POST to verify x402 payments", - body: { - paymentPayload: "PaymentPayload", - paymentRequirements: "PaymentRequirements", - }, +// Facilitator can now handle all Solana networks with automatic RPC creation +const svmSigner = toFacilitatorSvmSigner(svmAccount); + +const facilitator = new x402Facilitator() + .onBeforeVerify(async (context) => { + console.log("Before verify", context); + }) + .onAfterVerify(async (context) => { + console.log("After verify", context); + }) + .onVerifyFailure(async (context) => { + console.log("Verify failure", context); + }) + .onBeforeSettle(async (context) => { + console.log("Before settle", context); + }) + .onAfterSettle(async (context) => { + console.log("After settle", context); + }) + .onSettleFailure(async (context) => { + console.log("Settle failure", context); }); + +// Register EVM and SVM schemes using the new register helpers +registerExactEvmScheme(facilitator, { + signer: evmSigner, + networks: "eip155:84532", // Base Sepolia + deployERC4337WithEIP6492: true, }); +registerExactSvmScheme(facilitator, { + signer: svmSigner, + networks: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", // Devnet +}); + +// Initialize Express app +const app = express(); +app.use(express.json()); -app.post("/verify", async (req: Request, res: Response) => { +/** + * POST /verify + * Verify a payment against requirements + * + * Note: Payment tracking and bazaar discovery are handled by lifecycle hooks + */ +app.post("/verify", async (req, res) => { try { - const body: VerifyRequest = req.body; - const paymentRequirements = PaymentRequirementsSchema.parse(body.paymentRequirements); - const paymentPayload = PaymentPayloadSchema.parse(body.paymentPayload); - - // use the correct client/signer based on the requested network - // svm verify requires a Signer because it signs & simulates the txn - let client: Signer | ConnectedClient; - if (SupportedEVMNetworks.includes(paymentRequirements.network)) { - client = createConnectedClient(paymentRequirements.network); - } else if (SupportedSVMNetworks.includes(paymentRequirements.network)) { - client = await createSigner(paymentRequirements.network, SVM_PRIVATE_KEY); - } else { - throw new Error("Invalid network"); + const { paymentPayload, paymentRequirements } = req.body as { + paymentPayload: PaymentPayload; + paymentRequirements: PaymentRequirements; + }; + + if (!paymentPayload || !paymentRequirements) { + return res.status(400).json({ + error: "Missing paymentPayload or paymentRequirements", + }); } - // verify - const valid = await verify(client, paymentPayload, paymentRequirements, x402Config); - res.json(valid); + // Hooks will automatically: + // - Track verified payment (onAfterVerify) + // - Extract and catalog discovery info (onAfterVerify) + const response: VerifyResponse = await facilitator.verify( + paymentPayload, + paymentRequirements, + ); + + res.json(response); } catch (error) { - console.error("error", error); - res.status(400).json({ error: "Invalid request" }); + console.error("Verify error:", error); + res.status(500).json({ + error: error instanceof Error ? error.message : "Unknown error", + }); } }); -app.get("/settle", (req: Request, res: Response) => { - res.json({ - endpoint: "/settle", - description: "POST to settle x402 payments", - body: { - paymentPayload: "PaymentPayload", - paymentRequirements: "PaymentRequirements", - }, - }); -}); +/** + * POST /settle + * Settle a payment on-chain + * + * Note: Verification validation and cleanup are handled by lifecycle hooks + */ +app.post("/settle", async (req, res) => { + try { + const { paymentPayload, paymentRequirements } = req.body; -app.get("/supported", async (req: Request, res: Response) => { - let kinds: SupportedPaymentKind[] = []; + if (!paymentPayload || !paymentRequirements) { + return res.status(400).json({ + error: "Missing paymentPayload or paymentRequirements", + }); + } - // evm - if (EVM_PRIVATE_KEY) { - kinds.push({ - x402Version: 1, - scheme: "exact", - network: "base-sepolia", - }); - } + // Hooks will automatically: + // - Validate payment was verified (onBeforeSettle - will abort if not) + // - Check verification timeout (onBeforeSettle) + // - Clean up tracking (onAfterSettle / onSettleFailure) + const response: SettleResponse = await facilitator.settle( + paymentPayload as PaymentPayload, + paymentRequirements as PaymentRequirements, + ); + + res.json(response); + } catch (error) { + console.error("Settle error:", error); + + // Check if this was an abort from hook + if ( + error instanceof Error && + error.message.includes("Settlement aborted:") + ) { + // Return a proper SettleResponse instead of 500 error + return res.json({ + success: false, + errorReason: error.message.replace("Settlement aborted: ", ""), + network: req.body?.paymentPayload?.network || "unknown", + } as SettleResponse); + } - // svm - if (SVM_PRIVATE_KEY) { - const signer = await createSigner("solana-devnet", SVM_PRIVATE_KEY); - const feePayer = isSvmSignerWallet(signer) ? signer.address : undefined; - - kinds.push({ - x402Version: 1, - scheme: "exact", - network: "solana-devnet", - extra: { - feePayer, - }, + res.status(500).json({ + error: error instanceof Error ? error.message : "Unknown error", }); } - res.json({ - kinds, - }); }); -app.post("/settle", async (req: Request, res: Response) => { +/** + * GET /supported + * Get supported payment kinds and extensions + */ +app.get("/supported", async (req, res) => { try { - const body: SettleRequest = req.body; - const paymentRequirements = PaymentRequirementsSchema.parse(body.paymentRequirements); - const paymentPayload = PaymentPayloadSchema.parse(body.paymentPayload); - - // use the correct private key based on the requested network - let signer: Signer; - if (SupportedEVMNetworks.includes(paymentRequirements.network)) { - signer = await createSigner(paymentRequirements.network, EVM_PRIVATE_KEY); - } else if (SupportedSVMNetworks.includes(paymentRequirements.network)) { - signer = await createSigner(paymentRequirements.network, SVM_PRIVATE_KEY); - } else { - throw new Error("Invalid network"); - } - - // settle - const response = await settle(signer, paymentPayload, paymentRequirements, x402Config); + const response = facilitator.getSupported(); res.json(response); } catch (error) { - console.error("error", error); - res.status(400).json({ error: `Invalid request: ${error}` }); + console.error("Supported error:", error); + res.status(500).json({ + error: error instanceof Error ? error.message : "Unknown error", + }); } }); -app.listen(process.env.PORT || 3000, () => { - console.log(`Server listening at http://localhost:${process.env.PORT || 3000}`); +// Start the server +app.listen(parseInt(PORT), () => { + console.log("Facilitator listening"); }); diff --git a/examples/typescript/facilitator/package.json b/examples/typescript/facilitator/package.json index ad7e82008..cee29fd35 100644 --- a/examples/typescript/facilitator/package.json +++ b/examples/typescript/facilitator/package.json @@ -1,30 +1,39 @@ { - "name": "facilitator-example", - "private": true, + "name": "@x402/core-facilitator-typescript", + "version": "2.0.0", "type": "module", + "private": true, "scripts": { - "dev": "tsx index.ts", - "solana": "tsx solana.ts", - "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", - "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", - "lint": "eslint . --ext .ts --fix", - "lint:check": "eslint . --ext .ts" + "start": "tsx index.ts", + "dev": "tsx watch index.ts", + "build": "tsc", + "lint": "eslint .", + "format": "prettier --write .", + "typecheck": "tsc --noEmit" }, "dependencies": { - "dotenv": "^16.4.7", - "express": "^4.18.2", - "x402": "workspace:*" + "@scure/base": "^1.2.6", + "@solana/kit": "^2.1.1", + "@x402/core": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/extensions": "workspace:*", + "@x402/svm": "workspace:*", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "viem": "^2.21.54" }, "devDependencies": { "@eslint/js": "^9.24.0", - "eslint": "^9.24.0", - "eslint-plugin-jsdoc": "^50.6.9", - "eslint-plugin-prettier": "^5.2.6", + "@types/express": "^4.17.21", + "@types/node": "^22.10.1", "@typescript-eslint/eslint-plugin": "^8.29.1", "@typescript-eslint/parser": "^8.29.1", + "eslint": "^9.15.0", "eslint-plugin-import": "^2.31.0", - "prettier": "3.5.2", - "tsx": "^4.7.0", - "typescript": "^5.3.0" + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-prettier": "^5.2.6", + "prettier": "^3.3.3", + "tsx": "^4.19.2", + "typescript": "^5.7.2" } } diff --git a/examples/typescript/facilitator/tsconfig.json b/examples/typescript/facilitator/tsconfig.json index 78f9479b1..fc0e5250e 100644 --- a/examples/typescript/facilitator/tsconfig.json +++ b/examples/typescript/facilitator/tsconfig.json @@ -1,15 +1,19 @@ { "compilerOptions": { - "target": "ES2020", - "module": "ES2020", - "moduleResolution": "bundler", + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "lib": ["ES2022"], + "strict": true, "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, "skipLibCheck": true, - "strict": true, + "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, - "baseUrl": ".", - "types": ["node"] + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "./dist" }, - "include": ["index.ts"] + "include": ["*.ts"], + "exclude": ["node_modules", "dist"] } diff --git a/examples/typescript/fullstack/mainnet/.env-local b/examples/typescript/fullstack/mainnet/.env-local deleted file mode 100644 index 0b6d62fce..000000000 --- a/examples/typescript/fullstack/mainnet/.env-local +++ /dev/null @@ -1,3 +0,0 @@ -RESOURCE_WALLET_ADDRESS= -CDP_API_KEY_ID= -CDP_API_KEY_SECRET= \ No newline at end of file diff --git a/examples/typescript/fullstack/mainnet/app/api/x402/session-token/route.ts b/examples/typescript/fullstack/mainnet/app/api/x402/session-token/route.ts deleted file mode 100644 index 3d9293fc2..000000000 --- a/examples/typescript/fullstack/mainnet/app/api/x402/session-token/route.ts +++ /dev/null @@ -1 +0,0 @@ -export { POST } from "x402-next"; diff --git a/examples/typescript/fullstack/mainnet/middleware.ts b/examples/typescript/fullstack/mainnet/middleware.ts deleted file mode 100644 index f12d94057..000000000 --- a/examples/typescript/fullstack/mainnet/middleware.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { facilitator } from "@coinbase/x402"; -import { Address } from "viem"; -import { paymentMiddleware } from "x402-next"; - -const payTo = process.env.RESOURCE_WALLET_ADDRESS as Address; - -export const middleware = paymentMiddleware( - payTo, - { - "/protected": { - price: "$0.001", - network: "base", - config: { - discoverable: true, // make endpoint discoverable - description: "Access to protected content", - outputSchema: { - type: "text/html", - description: "Exclusive music content", - }, - }, - }, - }, - facilitator, - { - appName: "Mainnet x402 Demo", - appLogo: "/x402-icon-blue.png", - sessionTokenEndpoint: "/api/x402/session-token", - }, -); - -// Configure which paths the middleware should run on -export const config = { - matcher: ["/protected/:path*"], - runtime: "nodejs", -}; diff --git a/examples/typescript/fullstack/next/.env-local b/examples/typescript/fullstack/next/.env-local index 922c51636..794171a8a 100644 --- a/examples/typescript/fullstack/next/.env-local +++ b/examples/typescript/fullstack/next/.env-local @@ -1,3 +1,8 @@ -NEXT_PUBLIC_FACILITATOR_URL=https://x402.org/facilitator -NETWORK=base-sepolia -RESOURCE_WALLET_ADDRESS= +EVM_ADDRESS= +SVM_ADDRESS= +FACILITATOR_URL= + +CDP_CLIENT_KEY= +APP_NAME=Next x402 Demo +APP_LOGO=/x402-icon-blue.png + diff --git a/examples/typescript/fullstack/next/.prettierignore b/examples/typescript/fullstack/next/.prettierignore index 5bd240ba9..406cfdb76 100644 --- a/examples/typescript/fullstack/next/.prettierignore +++ b/examples/typescript/fullstack/next/.prettierignore @@ -3,6 +3,7 @@ dist/ node_modules/ coverage/ .github/ +.next/ src/client **/**/*.json *.md \ No newline at end of file diff --git a/examples/typescript/fullstack/next/README.md b/examples/typescript/fullstack/next/README.md index 286d0e25d..61431c2c8 100644 --- a/examples/typescript/fullstack/next/README.md +++ b/examples/typescript/fullstack/next/README.md @@ -1,30 +1,36 @@ # x402-next Example App -This is a Next.js application that demonstrates how to use the `x402-next` middleware to implement paywall functionality in your Next.js routes. +Next.js application demonstrating how to protect routes with a paywall using the `@x402/next` middleware. ## Prerequisites - Node.js v20+ (install via [nvm](https://github.com/nvm-sh/nvm)) - pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) -- A valid Ethereum address for receiving payments +- Valid EVM and SVM addresses for receiving payments +- URL of a facilitator supporting the desired payment network, see [facilitator list](https://www.x402.org/ecosystem?category=facilitators) ## Setup -1. Copy `.env-local` to `.env` and add your Ethereum address to receive payments: +1. Copy `.env-local` to `.env`: ```bash cp .env-local .env ``` +and fill required environment variables: + +- `FACILITATOR_URL` - Facilitator endpoint URL +- `EVM_ADDRESS` - Ethereum address to receive payments +- `SVM_ADDRESS` - Solana address to receive payments + 2. Install and build all packages from the typescript examples root: ```bash cd ../../ -pnpm install -pnpm build +pnpm install && pnpm build cd fullstack/next ``` -2. Install and start the Next.js example: +3. Run the server: ```bash pnpm dev ``` @@ -34,123 +40,238 @@ pnpm dev The app includes protected routes that require payment to access: ### Protected Page Route -The `/protected` route requires a payment of $0.01 to access. The page route is protected using the x402-next middleware: + +The `/protected` route is protected using `paymentProxy`. Page routes are protected using this approach: ```typescript -// middleware.ts -import { paymentMiddleware, Network, Resource } from "x402-next"; +// proxy.ts +import { paymentProxy } from "@x402/next"; +import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; +import { registerExactEvmScheme } from "@x402/evm/exact/server"; +import { registerExactSvmScheme } from "@x402/svm/exact/server"; +import { createPaywall } from "@x402/paywall"; +import { evmPaywall } from "@x402/paywall/evm"; +import { svmPaywall } from "@x402/paywall/svm"; + +const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl }); +const server = new x402ResourceServer(facilitatorClient); + +// Register schemes +registerExactEvmScheme(server); +registerExactSvmScheme(server); -const facilitatorUrl = process.env.NEXT_PUBLIC_FACILITATOR_URL as Resource; -const payTo = process.env.RESOURCE_WALLET_ADDRESS as Address; -const network = process.env.NETWORK as Network; +// Build paywall using builder pattern +const paywall = createPaywall() + .withNetwork(evmPaywall) + .withNetwork(svmPaywall) + .withConfig({ + appName: "Next x402 Demo", + appLogo: "/x402-icon-blue.png", + testnet: true, + }) + .build(); -export const middleware = paymentMiddleware( - payTo, +export const proxy = paymentProxy( { "/protected": { - price: "$0.01", - network, - config: { - description: "Access to protected content", - }, + accepts: [ + { + scheme: "exact", + price: "$0.001", + network: "eip155:84532", + payTo: evmAddress, + }, + { + scheme: "exact", + price: "$0.001", + network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + payTo: svmAddress, + }, + ], + description: "Premium music: x402 Remix", + mimeType: "text/html", }, }, - { - url: facilitatorUrl, - }, + server, + undefined, // paywallConfig (using custom paywall instead) + paywall, // custom paywall provider ); -// Configure which paths the middleware should run on export const config = { matcher: ["/protected/:path*"], - runtime: "nodejs", }; ``` -### Protected API Route -The `/api/weather` API route requires a payment of $0.01 to access. The API route is protected using the x402-next route wrapper. This is the recommened approach to protect API routes as it guarantees payment settlement only AFTER successful API responses (status < 400). API routes can also be protected by the x402-next middleware, however this will charge clients for failed API responses. +### Weather API Route (using withX402) + +The `/api/weather` route demonstrates the `withX402` wrapper for individual API routes: ```typescript // app/api/weather/route.ts import { NextRequest, NextResponse } from "next/server"; -import { withX402, Network, Resource } from "x402-next"; +import { withX402 } from "@x402/next"; +import { server, paywall, evmAddress, svmAddress } from "../../../proxy"; const handler = async (_: NextRequest) => { return NextResponse.json({ - report: { weather: "sunny", temperature: 70 } + report: { + weather: "sunny", + temperature: 72, + }, }); }; export const GET = withX402( handler, - payTo, { - price: "$0.01", - network, - config: { description: "Access to weather API" } + accepts: [ + { + scheme: "exact", + price: "$0.001", + network: "eip155:84532", + payTo: evmAddress, + }, + { + scheme: "exact", + price: "$0.001", + network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + payTo: svmAddress, + }, + ], + description: "Access to weather API", + mimeType: "application/json", }, - { url: facilitatorUrl }, - { appName: "Next x402 Demo", appLogo: "/x402-icon-blue.png" } + server, + undefined, // paywallConfig (using custom paywall from proxy.ts) + paywall, ); ``` ## Response Format ### Payment Required (402) + +``` +HTTP/1.1 402 Payment Required +Content-Type: application/json; charset=utf-8 +PAYMENT-REQUIRED: + +{} +``` + +The `PAYMENT-REQUIRED` header contains base64-encoded JSON with the payment requirements. +Note: `amount` is in atomic units (e.g., 1000 = 0.001 USDC, since USDC has 6 decimals): + ```json { - "error": "X-PAYMENT header is required", - "paymentRequirements": { - "scheme": "exact", - "network": "base", - "maxAmountRequired": "1000", - "resource": "http://localhost:3000/protected", - "description": "Access to protected content", - "mimeType": "", - "payTo": "0xYourAddress", - "maxTimeoutSeconds": 60, - "asset": "0x...", - "outputSchema": null, - "extra": null - } + "x402Version": 2, + "error": "Payment required", + "resource": { + "url": "http://localhost:3000/api/weather", + "description": "Access to weather API", + "mimeType": "application/json" + }, + "accepts": [ + { + "scheme": "exact", + "network": "eip155:84532", + "amount": "1000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "payTo": "0x...", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2", + "resourceUrl": "http://localhost:4021/weather" + } + } + ] } ``` ### Successful Response -```ts -// Headers + +``` +HTTP/1.1 200 OK +Content-Type: application/json; charset=utf-8 +PAYMENT-RESPONSE: + +{"report":{"weather":"sunny","temperature":72}} +``` + +The `PAYMENT-RESPONSE` header contains base64-encoded JSON with the settlement details: + +```json { - "X-PAYMENT-RESPONSE": "..." // Encoded response object + "success": true, + "transaction": "0x...", + "network": "eip155:84532", + "payer": "0x...", + "requirements": { + "scheme": "exact", + "network": "eip155:84532", + "amount": "1000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "payTo": "0x...", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2", + "resourceUrl": "http://localhost:4021/weather" + } + } } ``` +## paymentProxy vs withX402 + +The `paymentProxy` function is used to protect page routes. It can also protect API routes, however this will charge clients for failed API responses. + +The `withX402` function wraps API route handlers. This is the recommended approach to protect API routes as it guarantees payment settlement only AFTER successful API responses (status < 400). + +| Approach | Use Case | +|----------|----------| +| `paymentProxy` | Protecting page routes or multiple routes with a single configuration | +| `withX402` | Protecting individual API routes where you need precise control over settlement timing | + ## Extending the Example -To add more protected routes, update the middleware configuration: +To add more protected routes, update the proxy configuration: ```typescript -export const middleware = paymentMiddleware( - payTo, +export const proxy = paymentProxy( { "/protected": { - price: "$0.01", - network, - config: { - description: "Access to protected content", + accepts: { + scheme: "exact", + price: "$0.001", + network: "eip155:84532", + payTo: evmAddress, }, + description: "Access to protected content", }, - "/api/premium": { - price: "$0.10", - network, - config: { - description: "Premium API access", + "/premium": { + accepts: { + scheme: "exact", + price: "$0.10", + network: "eip155:84532", + payTo: evmAddress, }, + description: "Premium content access", }, - } + }, + server, + undefined, + paywall, ); export const config = { - matcher: ["/protected/:path*", "/api/premium/:path*"], - runtime: "nodejs", + matcher: ["/protected/:path*", "/premium/:path*"], }; ``` + +**Network identifiers** use [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) format, for example: +- `eip155:84532` — Base Sepolia +- `eip155:8453` — Base Mainnet +- `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` — Solana Devnet +- `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` — Solana Mainnet diff --git a/examples/typescript/fullstack/next/app/api/weather/route.ts b/examples/typescript/fullstack/next/app/api/weather/route.ts index ba83d2e6e..1fd9cd201 100644 --- a/examples/typescript/fullstack/next/app/api/weather/route.ts +++ b/examples/typescript/fullstack/next/app/api/weather/route.ts @@ -1,49 +1,69 @@ import { NextRequest, NextResponse } from "next/server"; -import { withX402, Network, Resource } from "x402-next"; -import { Address } from "viem"; - -const facilitatorUrl = process.env.NEXT_PUBLIC_FACILITATOR_URL as Resource; -const payTo = process.env.RESOURCE_WALLET_ADDRESS as Address; -const network = process.env.NETWORK as Network; +import { withX402 } from "@x402/next"; +import { declareDiscoveryExtension } from "@x402/extensions/bazaar"; +import { server, paywall, evmAddress, svmAddress } from "../../../proxy"; /** * Weather API endpoint handler * - * @param {NextRequest} _ - The incoming request object + * This handler returns weather data after payment verification. + * Payment is only settled after a successful response (status < 400). + * + * @param _ - Incoming Next.js request * @returns JSON response with weather data */ const handler = async (_: NextRequest) => { - const response = NextResponse.json( + return NextResponse.json( { report: { weather: "sunny", - temperature: 70, + temperature: 72, }, }, { status: 200 }, ); - return response; }; /** - * Protected weather API endpoint - * Payment is only settled after successful response (status < 400) + * Protected weather API endpoint using withX402 wrapper + * + * This demonstrates the v2 withX402 wrapper for individual API routes. + * Unlike middleware, withX402 guarantees payment settlement only after + * the handler returns a successful response (status < 400). */ export const GET = withX402( handler, - payTo, { - price: "$0.01", - network, - config: { - description: "Access to weather API", + accepts: [ + { + scheme: "exact", + price: "$0.001", + network: "eip155:84532", // base-sepolia + payTo: evmAddress, + }, + { + scheme: "exact", + price: "$0.001", + network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", // solana devnet + payTo: svmAddress, + }, + ], + description: "Access to weather API", + mimeType: "application/json", + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + report: { + weather: "sunny", + temperature: 72, + }, + }, + }, + }), }, }, - { - url: facilitatorUrl, - }, - { - appName: "Next x402 Demo", - appLogo: "/x402-icon-blue.png", - }, + server, + undefined, // paywallConfig (using custom paywall from proxy.ts) + paywall, ); diff --git a/examples/typescript/fullstack/next/app/globals.css b/examples/typescript/fullstack/next/app/globals.css index e4793b23b..ab356f17f 100644 --- a/examples/typescript/fullstack/next/app/globals.css +++ b/examples/typescript/fullstack/next/app/globals.css @@ -1,33 +1,29 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss"; -:root { - --background: #ffffff; - --foreground: #171717; +@theme { + --color-background: #ffffff; + --color-foreground: #171717; } @media (prefers-color-scheme: dark) { - :root { - --background: #1a1a2e; - --foreground: #ededed; + @theme { + --color-background: #1a1a2e; + --color-foreground: #ededed; } } body { - color: var(--foreground); - background: var(--background); + color: var(--color-foreground); + background: var(--color-background); font-family: Arial, Helvetica, sans-serif; } -@layer utilities { - .full-bleed { - width: 100vw; - margin-left: calc(50% - 50vw); - } +@utility full-bleed { + width: 100vw; + margin-left: calc(50% - 50vw); +} - .unset-full-bleed { - width: unset; - margin-left: unset; - } +@utility unset-full-bleed { + width: unset; + margin-left: unset; } diff --git a/examples/typescript/fullstack/next/app/layout.tsx b/examples/typescript/fullstack/next/app/layout.tsx index 26396a893..3aba2308a 100644 --- a/examples/typescript/fullstack/next/app/layout.tsx +++ b/examples/typescript/fullstack/next/app/layout.tsx @@ -13,8 +13,8 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: 'x402.org', - description: 'A chain-agnostic protocol for web payments', + title: "x402 Next.js Demo", + description: "A chain-agnostic protocol for web payments", }; export default function RootLayout({ @@ -25,19 +25,8 @@ export default function RootLayout({ return ( - - - - + + @@ -49,3 +38,4 @@ export default function RootLayout({ ); } + diff --git a/examples/typescript/fullstack/next/app/page.tsx b/examples/typescript/fullstack/next/app/page.tsx index 34fc13970..65de5ee65 100644 --- a/examples/typescript/fullstack/next/app/page.tsx +++ b/examples/typescript/fullstack/next/app/page.tsx @@ -1,5 +1,5 @@ -import Link from 'next/link'; -import WordmarkCondensed from './assets/x402_wordmark_light.svg'; +import Link from "next/link"; +import Image from "next/image"; export default function Home() { return ( @@ -8,8 +8,14 @@ export default function Home() { {/* Hero Section */}
-
- +
+ x402 logo

Fullstack demo powered by Next.js @@ -19,14 +25,20 @@ export default function Home() { href="/protected" className="px-6 py-3 bg-blue-600 hover:bg-blue-700 rounded-lg font-mono transition-colors text-white" > - Live demo + Protected page + + + Protected API